From: Jean Privat Date: Fri, 6 Feb 2015 01:14:55 +0000 (+0700) Subject: Merge: Generalize instance creation service so FFI can use it X-Git-Tag: v0.7.2~25 X-Git-Url: http://nitlanguage.org?hp=372a61b6f9f8490faae2e4cecb98381a12f6cb15 Merge: Generalize instance creation service so FFI can use it Move up instance creation from ANew to AbstractCompilerVisitor so they can be used from the FFI implementation. Allows to call extern constructors of extern classes from extern code, and fix #1145. Pull-Request: #1150 Reviewed-by: Lucas Bajolet Reviewed-by: Alexandre Terrasa Reviewed-by: Jean Privat --- diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index b212fed..f286f02 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -1387,6 +1387,24 @@ abstract class AbstractCompilerVisitor # Generate a alloc-instance + init-attributes fun init_instance(mtype: MClassType): RuntimeVariable is abstract + # Allocate and init attributes of an instance of a standard or extern class + # + # Does not support universals and the pseudo-internal `NativeArray` class. + fun init_instance_or_extern(mtype: MClassType): RuntimeVariable + do + var recv + var ctype = mtype.ctype + assert mtype.mclass.name != "NativeArray" + if ctype == "val*" then + recv = init_instance(mtype) + else if ctype == "char*" then + recv = new_expr("NULL/*special!*/", mtype) + else + recv = new_expr("({ctype})0/*special!*/", mtype) + end + return recv + end + # Set a GC finalizer on `recv`, only if `recv` isa Finalizable fun set_finalizer(recv: RuntimeVariable) do @@ -2883,22 +2901,17 @@ redef class ANewExpr do var mtype = self.recvtype assert mtype != null - var recv - var ctype = mtype.ctype + if mtype.mclass.name == "NativeArray" then assert self.n_args.n_exprs.length == 1 var l = v.expr(self.n_args.n_exprs.first, null) assert mtype isa MGenericType var elttype = mtype.arguments.first return v.native_array_instance(elttype, l) - else if ctype == "val*" then - recv = v.init_instance(mtype) - else if ctype == "char*" then - recv = v.new_expr("NULL/*special!*/", mtype) - else - recv = v.new_expr("({ctype})0/*special!*/", mtype) end + var recv = v.init_instance_or_extern(mtype) + var callsite = self.callsite.as(not null) var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) var res2 = v.compile_callsite(callsite, args) diff --git a/src/compiler/compiler_ffi.nit b/src/compiler/compiler_ffi.nit index dea917b..42423f9 100644 --- a/src/compiler/compiler_ffi.nit +++ b/src/compiler/compiler_ffi.nit @@ -388,7 +388,7 @@ redef class MExplicitCall var recv_var = null if mproperty.is_init then var recv_mtype = recv_mtype - recv_var = nitni_visitor.init_instance(recv_mtype) + recv_var = nitni_visitor.init_instance_or_extern(recv_mtype) nitni_visitor.add("{mtype.ctype} recv /* var self: {mtype} */;") nitni_visitor.add("recv = {recv_var};") else diff --git a/tests/sav/test_ffi_c_new_extern.res b/tests/sav/test_ffi_c_new_extern.res new file mode 100644 index 0000000..ae8c4c1 --- /dev/null +++ b/tests/sav/test_ffi_c_new_extern.res @@ -0,0 +1,2 @@ +1234 +5678 diff --git a/tests/test_ffi_c_new_extern.nit b/tests/test_ffi_c_new_extern.nit new file mode 100644 index 0000000..e9b46d2 --- /dev/null +++ b/tests/test_ffi_c_new_extern.nit @@ -0,0 +1,45 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Test callback to an extern constructor from extern code + +import standard::string + +extern class IntPtr `{ int* `} + new (v: Int) `{ + int *r = malloc(sizeof(int)); + *r = v; + return r; + `} + + redef fun to_s import NativeString, NativeString.to_s `{ + int len = snprintf(NULL, 0, "%d", *recv) + 1; + char *c = new_NativeString(len); + sprintf(c, "%d", *recv); + return NativeString_to_s(c); + `} +end + +fun foo: IntPtr import IntPtr `{ + int *c = new_IntPtr(5678); + return c; +`} + +var a = new IntPtr(1234) +a.to_s.output +"\n".output + +var b = foo +b.to_s.output +"\n".output