Re: [问题] C#引用C++的dll用DLLIMPORT失败 需转换?

楼主: lightyen (lightyen)   2018-08-08 11:15:08
※ 引述《Stevenashh (YO!!!)》之铭言:
: 开发平台(Platform): WIN 7
: 编译器: visual studio 2017
: 额外使用到的函数库(Library Used): 外部dll
: 问题(Question):
: 平时是写C#,但近期需要使用C#呼叫其他厂商c++的dll(不晓得是manage还unmanage)
: 查询利用DLLIMPORT可以呼叫 但失败了(应该不是使用错误)
: 出现的错误如图 https://imgur.com/a/Hw9DX6G
: 原文:https://goo.gl/if1WsW
: Google到的原因是没有c++没有实作clr(=Unmaged?)
: 但我看所有DLLIMPORT的教学都是说C#可以直接呼叫Unmanaged
: 抱歉因为不太懂c++
: 跪求大大解惑是什么原因,或是可以提供我关键字让我继续往下找
: 我应该做些什么动作才能将这包dll转换成C#可以IMPORT的版本
: 补充说明(Supplement):
: 愿以1000P微薄小心意回馈
首先要确认的是要引用的 dll 是 managed 或是 unmanaged。
- managed
指的是给CLR托管 有内存垃圾回收C#,VB,C++/CLI 属于这类。
- unmanaged
非托管的代码则是要自己得要处理内存问题,
传统的windows api或者COM接口或者是其他人写的native C++都是这种形式的。
(称native只是为了和C++/CLI有所区隔,可以想成是又快又猛又易翻车的C++)
依你要的需求,大概是使用C#来呼叫unmanaged code相去不远了。
这种用C#和原生C++掺在一块做牛丸的混合编程,
其中最直接相关库的就是 System.Runtime.InteropServices
这东西搞起来非常的麻烦,不仅要知道native c++的api形式,
还要熟悉C++与C#的用法规则,不然很容易出错也不好debug。
## 在此我先弄一个范例:
https://github.com/lightyen/WpfMessageBox
其中建立了一个WPF专案,设计一个按钮,
在点选了按钮之后会去呼叫user32.dll中的MessageBox来显示一个对话框。
如果你有一些工具软件去查看user32.dll,(例如DLL Export Viewer)
你会发现user32.dll存在两个与MessageBox有关的Function,
一个是A结尾一个是W结尾,A指的是ASCII,W指的是宽字符。
不过我们已经把CharSet设成Auto了,.NET平台会自动地去选择合适的。
(比较重要的点是在C#中,string全部是宽字符的,要和unmanaged code互通时要多留意)
## 好了,现在我们可以来实作牛丸了
首先新增一个*.cs 然宣告一个static class来当我们的接口参考,
然后再宣告一个static extern方法来描述MessageBox这个函式,
把函式名称、参数形式、返回值依照API文件规范依样画葫芦。
IntPtr在C++中代表的就是指标,而IntPtr.Zero则代表NULL,
HWND是一个视窗的handle,也是一个整数。
(其实指标在内存中也不过是一个整数罢了。)
(user32.dll不需要填绝对路径,因为windows已经内定注册了,
第三方的library应该还是要填详细的路径。)
LPCTSTR =>'一个tchar的唯读字串',在这里用一个string代表。
使用了这个方法后,平台会隐隐地偷偷地把string的内容先放到unmanaged空间,
然后再做参数传给MessageBox。
假若今天要传的是一个物件(void*),
则我们必须先从unmanaged要一块内存空间,然后填上相应资料,
在透过IntPtr写入(或读出),最后用完后还要记得回收内存,
整个过程真的虾鸡巴麻烦的。
参考:System.Runtime.InteropServices.Marshal
AllocHGlobal,FreeHGlobal,SizeOf
## 最后设计的部分
许多c++的函式都用一个整数代表功能的体现,
在C#中我们可以来为这些功能(flag)写成一个enum,加些注解,
或者把一些资料包装成一个class,再加上一些额外的功能,
使得在调用这些unmanaged code能更加舒服一些。
## 更多的范例
https://github.com/lightyen/COMInterop
## 更多的关键字
pinvoke, Interop, DllImport, Marshal,
IntPtr, UnmanagedType, StructLayout, MarshalAs
作者: petercoin (彼得币)   2018-08-08 13:40:00
给个推~
作者: Schottky (顺风相送)   2018-08-08 17:04:00
推,Unicode/ASCII function 确实常常制造问题要分清楚
作者: largesperm (reindeer)   2018-08-08 22:08:00
受益良多 推推
作者: s4300026 (s4300026)   2018-08-09 09:49:00
先推再看
作者: tinlans ( )   2018-08-12 05:54:00
对岸有一本 ISBN 是 9787115204349 的书不错看。虽说绝版但还买得到,只是书有附光盘不能走正常管道出境
作者: Killercat (杀人猫™)   2018-08-17 08:18:00
其实说麻烦就Marshal那段特别讨厌而已,很多c#其实都是刻UI然后把state全部给dll管的话 其实难度不高dll要expose任何结构出来的是地狱麻烦鬼...

Links booklink

Contact Us: admin [ a t ] ucptt.com