swig是一个生成其他高级语言调用c和C++代码的工具,比如,大家都知道java的jni,可能没写过,因为非常麻烦,swig可以帮助生成这样的代码,编译生成的代码后,它会生成java类和c代码文件。分别编译后,就可以在java中调用c++的库了。
swig非常强大,建议每个程序员都学会它。
swig支持十几种编程语言,包括java,c#,javascript,python等,常见的编程语言都被支持了。
官方基础入门教程:
看lazy的部分,直接include c++的头文件。一般情况下,是不会自己动手写interface的。
当包含了C++的头文件之后,要使用 -c++,否则无法正确生成代码。
如:
swig -c++ -csharp example.i
1.如何忽略某些方法
有些c和c++的代码,只写了函数声明,但是没有函数的实现,而swig生成的代码会调用这些方法,所以Link的时候会找不到符号。
这种情况,用%ignore
%ignore a::somemethod;
%include xxx.h
会忽略所有名字为a::somemethod的方法。但注意,ignore要放在被包含的头文件解析之前。也就是在%xxx.h前面
2.如何生成namespace
默认情况下,所有的生成的类和结构体,枚举都没有namespace,即使c++代码里面声明了namespace
假如有个c++类叫 MyNameSpace::MyClass
%nspace MyNameSpace::MyClass;//注意行结束要有分号
就可以生成带有namespace的代码了。缺点是每个类都要声明一次。
如果想在所有代码的前面都将上一个namespace,可以这样使用命令行
swig -c++ -csharp -namespace NsPrefix example.i
这样生成的类叫 NsPrefix.MyNameSpace.MyClass
3. DllImport指定Dll名称
可以在使用命令行的时候,加上 -dllimport <name>
补充2个问题,如何映射指针
swig对于指针,默认是不做转换的,它只会把这个类型看作是“某个对象的指针”,比如,char* ,它会生成一个叫SWIGTYPE_p_char的类型,还保存这个指针。语法上是没问题,实际却很难使用,可以说基本没有实用价值。这种情况,要做TypeMap,具体我也研究的不深,只是解决了几个自己用到的问题。
1.原生类型的数组
比如,原来的函数声明是:
void MyFunction(int* data, int length);
%include <arrays_csharp.i>;//这是一个Swig定义好的TypeMap
%apply int FIXED[] {int * data}//data是要作用的参数名
%csmethodmodifiers MyFunction "public unsafe";//如果不加这句,生成的C#函数会因为缺少unsafe而出错,因为它生成的代码是使用fixed,需要unsafe上下文
2.对于stl的类
比如,std::string,希望它映射为c#的string,否则没法处理
这个swig也预定义了TypeMap,只要
%include <stl.i>
就可以了。
3.字符数组 char**
这个希望把它映射为C#的string[],否则没法调用它,这种情况就要自定义TypeMap
CSHARP_ARRAYS(char *, string)
%typemap(imtype, inattributes="[,System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPArray, SizeParamIndex=0, ArraySubType=System.Runtime.InteropServices.UnmanagedType.LPStr)]") char *INPUT[] "string[]"
%apply char *INPUT[] { char * shaderStrings[] }//例子1
%apply char *INPUT[] { char ** s }//例子2,与例1不同,char**和char* []是不同类型,如果写错了会不起作用
















