这几天有遇到要用 C#调用 C++的 dll函数的情况。C#不能直接调用 C++的dll,需要转化。

      因为之前没有用过,所有网上找了很多资料,但转化的过程中,仍然踩了很多雷。

 

     雷1:无法找到函数的入口点;

     雷2:函数堆栈不对称;

 

     下面,记录我踩雷及排雷的过程。

 

     1,首先需要准备相关的数据转化。

    

       常用的数据C++ 与C# 对照表:

       C++                      C#

      int  *port             ref   int

      LPVOID             Intptr

      BSTR/LPCSTR/LPCTSTR               string

      BOOL                Boolean

     CHAR/WCHAR     char

 

     2,转化

    C++:

    __declspec(dllexport) int DBSLDD_InitSerialPort(int nPortID, LPVOID *pHandle);

 

        转化成C#:

        [DllImport("LEDDriver.dll", EntryPoint = "DBSLDD_InitSerialPort", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int DBSLDD_InitSerialPort(int nPortID, ref IntPtr pHandle);

 

       没毛病,很完整。run 一下

      C# 调用 C++或C的dll

     没有找到,接口!!!!????  

     直接怀疑人生。

     气冲冲的找 提供dll的人,妹的,是不是给我的dll错了,耍人咧???

    结果人家信誓旦旦的说,木有问题了,还在我面前用C++完美的run了一下。

    接口没有问题,为啥我的提示无法找到入口点呢, 直接懵逼。

    痛苦,纠结中.............

    突然想到,为啥不用反编译工具查看一下这个dll是否有这个接口。

 

   结果找来这个工具,C# 调用 C++或C的dll

    

     C# 调用 C++或C的dll

     木问题呀,有这个方法。

 

    再仔细一看函数名的前后有很多 ooxx,莫非是缺少这些符号的问题,复制函数名:[email protected]@[email protected]

      果然包括那些  ooxx。

        改成:

        [DllImport("LEDDriver.dll", EntryPoint = "[email protected]@[email protected]", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]       
        public static extern int DBSLDD_InitSerialPort(int nPortID, ref IntPtr pHandle);

C# 调用 C++或C的dll

     果然,接口的问题,搞定了。

     不知道为什么有那些 ooxx,可能是生成dll编译器的问题。

 

       新的问题有来了、、、、、、     

 

      要炸了,有没有、、、、、、

 

      继续找问题中、、、、、、、

 

      最后查到,CallingConvention = CallingConvention.StdCall。

C# 调用 C++或C的dll

        C# ,应该是调用放清零堆栈,改为:CallingConvention = CallingConvention.Cdecl。可能是用C++生成的dll需要这样配置。

        完成的,

           [DllImport("LEDDriver.dll", EntryPoint = "[email protected]@[email protected]", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]       
        public static extern int DBSLDD_InitSerialPort(int nPortID, ref  IntPtr pHandle);

        运行通过,OK了。

 

         到此,所有的雷已经排完,心情舒畅哈。

 

相关文章: