可能是最简单的把C++Lib包装成C#可用dll的方法

 (想直接看结果的直接翻到最后)

之前对C++接触不多,最近工作需要,第三方给了一个C++的lib库,我们需要把它封装一下在C#中调用。对方要是直接给Dll就省事了。。。

研究了一下,基本有三个方向:

1. 建立CLI类型的,或者叫Managed的基于.NET的dll,这样c#可以直接进行引用。

2. 建立native的c++ dll,然后在C#用 dllimport的方式调用。

3. 建立com组件。

一开始感觉第一种很美好。直接加到reference中就能像引用一个C#的dll一样使用了。而且有一个好处是,我可以把这个dll工程和我的调用的C#工程放在一个solution中,然后在调试的时候,断点能直接进入到这个C++的工程中。这点要调试起来是很美好的哦。

方法可以参考这个:

在Header中引入头文件,在Resources中引入Lib文件。

这样在GoWrapper.cpp中就可以把需要的函数封装一下了。

 

这里可以选择更好的封装方式,比如对于原有的C++函数使用指针来返回结果的方式,我们可以使用一个自定义的类来返回之类的。但是考虑到要包装很多的函数,为了简便,最好让包装好的函数看起来和原有的函数差不多,对于指针可以通过ref或者out的方式来调用。

这样在调用的时候,就可以像下面这样调用:

注意如果想要用ref的方式调用的话,用下面这种来声明:

到现在,CLI的Managed dll方式基本已经完成了。可是想想如果要包装的时候,这一百多个函数的类型转换也将会是很大的一个工作量。我决定再尝试一下native dll的方式,虽然不能在同一个solution中debug,但是毕竟包装起来方便一些,只好忍忍了。

参考文档:

这里我必须使用一个EntryPoint=“#1”来指定我这个函数的entrypoint,因为生成的dll里面,export的函数的entrypoint的名称后面有一串 @xxxx 的东西。这个entrypoint 可以使用depends打开查看,可以使用名称或者序号。这样很不方便对不对,我用过的dllimport没有哪个是要这么搞的。为了解决这个问题,我们需要用到一个DEF文件。在properties中可以指定所使用的DEF文件,不过如果你自己添加一个DEF文件的话,它会被自动添加到Properties的设置中的,其实你不需要手动去指定它。

Def文件的作用就是告诉编译程序,我要把哪个函数用来export,用什么样的名称来export。当然,有了这个DEF文件,就可以不需要__declspec(dllexport) int的声明了。

修改之后的头文件:

修改之后的def文件:

调用方:

到现在,应该还比较圆满了。虽然我么有了调试C++库的便利,但是包装几百个函数也容易一些。只要直接把那个函数return回去就好了。

正当这时,凝望着我可爱的头文件。我忽然想起,当用depends查看生成的dll的时候。在依赖中是可以看到第三方的函数的。它们貌似也都加过 __declspec的前缀。那么既然它都加过了。那我还再Wrap一遍干啥???试了一下。把DEF文件删掉,把我加的Wrapper删掉,把我加的头文件也删掉。试了一下,可以用!!!

最终,其实就只是创建了一个native的dll,在resources里面加上了第三方的lib文件而已。别的自己的头文件和cpp文件一个都不用加的。有一种“慕然回首,那人却在灯火阑珊处”的感觉。虽然转了一圈,但是也算对于各种DLL的知识都有了了解,也算是有很多的收获了。而且这个方法适用的前提在于第三方已经把自己的函数都添加了 declspec的前缀。如果没有的话,可以简单的通过添加 DEF文件的方式来export出想要的方法。

附一个DEF文件的文档:https://docs.microsoft.com/zh-cn/cpp/build/reference/module-definition-dot-def-files?view=vs-2017

转载请注明出处!!

 

欢迎转载,转载请注明出处。如果觉得有一丁点的帮助请点击一下推荐。多谢。https://www.cnblogs.com/zzpbuaa/p/10061831.html
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信