(不幸的是,SWIG的文档很难解析,在线示例似乎很少见。所以我来到这里。)
假设C ++函数对类类型使用这种典型的返回样式:
void func(Class& out);
使用SWIG,这个函数应该用C#包装:
Class func();
根据我的发现,我可以使用类型图来完成此任务。
假设Class
实际上是int
,我根据我发现的示例尝试了以下内容:
%include <typemaps.i>
%{
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);
}
}
}
如何实现我想要的功能签名,以及如何将其传输到对象类型?
答案 0 :(得分:0)
我觉得在C#中找到了一种具体的方法,尽管它应该可以扩展到其他语言。
考虑这个SWIG界面,我已经为戏剧效果添加了额外的参数:
%include <typemaps.i>
%{
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方法的返回值。
以下是示例输出,证明它像魅力一样:
<强> 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
需要替换为其他特定语言的{{1}}才能与其他语言一起使用,但是我发现没有与语言无关的方法。
为了使用多种类型和功能轻松完成这项工作,可以定义一个宏。