Importing C++ dll to C#

本文关键字:to dll C++ Importing | 更新日期: 2023-09-27 18:14:27

我是c#新手,请帮助我解决以下问题。

我正在尝试导入c++ dll到我的c#代码,我得到以下错误。

调用PInvoke函数'SerialInterface!Form1::ReadTagData'使堆栈不平衡。这可能是因为托管的PInvoke签名与非托管的目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

下面是c#代码
const int buffSize = 33;
const int addr = 112;
const int readBytes = 8;
[DllImport(@"C:'Visual Studio 2010'Projects'SerialInterface'SerialInterface'bin'Debug'AP4600_SDK.dll")]
public static extern int ReadTagData(string tagID, string tagBuffer, Int32 szTagDataBuf, Int32 TagAddress, Int32 nBytes);
string asciiRead = "";
int s = ReadTagData(TagId, asciiRead, buffSize, addr, readBytes);

AP4600_SDK.dll中的ReadTagData函数定义为

AP4600_SDK_API int ReadTagData(
const char *pTagId,     /* TagId of tag to be read, from Identify */
char *pTagDataBuf,      /* (Output) The data read (ASCII representation of HEX), min size is 2*nBytes+1 (33 for Allegro) */
size_t szTagDataBuf,    /* Size of TagDataBuf, minimum is 2*nBytes+1 (33 for Allegro) */
int TagAddress,         /* Address of first byte to read */
size_t nBytes           /* Number of bytes to read (between 1 and 8, inclusive) */
);                      /* Returns zero for success, non zero failure */

Importing C++ dll to C#

以下是我能看到的错误:

  • 根据宏AP4600_SDK_API的定义,调用约定可能是错误的。我不能肯定,因为我看不到AP4600_SDK_API的评估结果。您可能需要在p/invoke中显式指定调用约定。目前使用默认的CallingConvention.StdCall
  • 第二个参数是一个可修改的缓冲区,所以必须是StringBuilder而不是' string '。
  • 两个size_t参数应该是指针大小的。使用UIntPtr .

所以假设调用约定是StdCall,它将是:

[DllImport(@"...", CallingConvention.StdCall)] // or perhaps CallingConvention.Cdecl
public static extern int ReadTagData(
    string tagID, 
    StringBuilder tagBuffer, 
    UIntPtr szTagDataBuf, 
    int TagAddress, 
    UIntPtr nBytes
);

这样写:

StringBuilder tagBuffer = new StringBuilder(nBytes*2+1)
int retval = ReadTagData(tagId, tagBuffer, tagBuffer.Capacity, addr, nBytes);
if (retval != 0)
    // handle error
// output can now be read with tagBuffer.ToString() 

您收到的错误消息中明确说明了问题。

例如,c++中的

char *pTagDataBuf与c#中的string pTagDataBuf不一样。c#有托管字符串。char*使用非托管指针。您可能需要使用不安全的代码块来访问该函数。

如果您试图将32位的dll加载到64位的项目或vica verca中,也会显示此错误信息。