使用SWIG,如何将C ++ void func(Class&out)包装为C#Class func()?

(不幸的是,SWIG的文档很难解析,在线示例似乎很少见。所以我来到这里。)

假设C ++函数对类类型使用这种典型的返回样式:

void func(Class& out); 

使用SWIG,这个函数应该用C#包装,如下所示:

 Class func(); 

从我发现的,我可以使用类型图来实现这一目标。

假设Class实际上是int ,我根据我发现的例子尝试了以下内容:

 %include  %{ void func(int& pOut); %} %apply int &OUTPUT { int &pOut } void func(int& pOut); 

许多例子(尽管倾向于Python)表明这应该创建一个没有输出int参数的函数。

但是,我使用了以下命令行:

 swig.exe -namespace Test -o .\Test.cxx -c++ -module Test -csharp -outdir . test.i 

这输出以下Test.cs:

 namespace Test { using System; using System.Runtime.InteropServices; public class Test { public static void func(out int pOut) { TestPINVOKE.func(out pOut); } } } 

如何实现我想要的function签名,以及如何将其转换为对象类型?

看起来我已经找到了一种在C#中专门执行此操作的方法,尽管它应该可以扩展到其他语言。

考虑一下这个SWIG界面,我在其中添加了额外的参数以获得显着的效果:

 %include  %{ class MyClass{}; void func(MyClass& pOut, int x); MyClass* func2(int x); %} %typemap(ctype, out="void *") void func "" %typemap(imtype, out="global::System.IntPtr") void func "" %typemap(cstype, out="MyClass") void func "" %typemap(in, numinputs=0, noblock=1) MyClass &pOut { $1 = new MyClass(); } %typemap(argout, noblock=1) MyClass &pOut { $result = $1; } %typemap(csout, excode=SWIGEXCODE) void func { IntPtr cPtr = $imcall;$excode MyClass ret = (cPtr != IntPtr.Zero) ? null : new MyClass(cPtr, $owner); return ret; } class MyClass{}; void func(MyClass& pOut, int x); MyClass* func2(int x); 

我也包含了func2以及正确的签名。

前3 %typemap改变了C ++包装函数,C#interop方法和C#包装方法的返回类型。

%typemap(in)删除无关的输出参数,并添加代码以在其位置使用新对象。 奇迹般地,这也使其他论点保持不变。

%typemap(argout)使用输出参数值作为新创建的返回值。

%typemap(csout)重写C#包装器方法代码以使用interop方法的返回值,就像在正常情况下一样。

以下是示例输出,certificate它像魅力一样:

Test.cxx

 SWIGEXPORT void * SWIGSTDCALL CSharp_func(int jarg2) { void * jresult ; MyClass *arg1 = 0 ; int arg2 ; arg1 = new MyClass(); arg2 = (int)jarg2; func(*arg1,arg2); jresult = arg1; return jresult; } SWIGEXPORT void * SWIGSTDCALL CSharp_func2(int jarg1) { void * jresult ; int arg1 ; MyClass *result = 0 ; arg1 = (int)jarg1; result = (MyClass *)func2(arg1); jresult = (void *)result; return jresult; } 

TestPINVOKE.cs

 [DllImport("Test", EntryPoint="CSharp_func")] public static extern global::System.IntPtr func(int jarg2); [DllImport("Test", EntryPoint="CSharp_func2")] public static extern IntPtr func2(int jarg1); 

test.cs中

 public class Test { public static MyClass func(int x) { IntPtr cPtr = TestPINVOKE.func(x); MyClass ret = (cPtr != IntPtr.Zero) ? null : new MyClass(cPtr, false); return ret; } public static MyClass func2(int x) { IntPtr cPtr = TestPINVOKE.func2(x); MyClass ret = (cPtr == IntPtr.Zero) ? null : new MyClass(cPtr, false); return ret; } } 

C#特定的%typemap需要替换为其他语言特定的类型%typemap ,以便与其他语言一起使用,但是我发现没有与语言无关的方法。

为了使用多种类型和function轻松完成这项工作,可以定义一个宏。