使用SWIG,如何将C++void func(Class&out)包装为C#类func()?
With SWIG, how do you wrap C++ void func(Class& out) as C# Class func()?
(不幸的是,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
这将输出以下测试.cs:
namespace Test {
using System;
using System.Runtime.InteropServices;
public class Test {
public static void func(out int pOut) {
TestPINVOKE.func(out pOut);
}
}
}
如何实现所需的函数签名,以及如何将其转换为对象类型?
看起来我已经找到了一种专门在 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# 互操作方法和 C# 包装器方法的返回类型。
该%typemap(in)
将删除无关的输出参数,并添加代码以在其位置使用新对象。这也奇迹般地使其他论点完好无损。
%typemap(argout)
使用输出参数值作为新创建的返回值。
%typemap(csout)
重写 C# 包装方法代码,以利用互操作方法的返回值,就像在正常情况下一样。
以下是证明它像魅力一样工作的示例输出:
测试.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);
测试.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
需要替换为其他特定于语言的才能与其他语言一起使用,但唉,我没有发现与语言无关的方法可以做到这一点。
为了使用多种类型和函数轻松完成此操作,可以定义宏。
相关文章:
- 如何在c++17中制作一个模板包装器/装饰器
- std::vector的包装器,使数组的结构看起来像结构的数组
- 如何在c++迭代器类型中包装std::chrono
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- 用pybind11包装C++抽象类时出错
- 为左值和右值的包装器实现C++范围
- C结构,其指针将被包装在unique_ptr中
- 如何包装第三方DLL在R中使用
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 将 N-arg 函数包装到另一个函数中
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 包装一个对象并假装它是一个 int
- 使用 Python Extension API 包装复杂C++类
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 包装C++类时不完整的类型 GLFWwindow
- 将函数包装器转换为 std::function
- C++函数包装器来捕获某些信号
- 表观调用前面的表达式必须具有指向 func 类型的指针
- 创建包装升压适配器的自定义范围类
- 使用SWIG,如何将C++void func(Class&out)包装为C#类func()?