简体   繁体   中英

Importing C++ dll to C#

I am new to C#, Please help me with below case.

I am trying to import C++ dll into my C# Code and I am getting the following error.

A call to PInvoke function 'SerialInterface!SerialInterface.Form1::ReadTagData' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

Below is the C# code

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);

The function ReadTagData definition in the AP4600_SDK.dll is

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 */

Here are the mistakes that I can see:

  • Depending on how the macro AP4600_SDK_API is defined, the calling convention could be wrong. I can't say for sure since I can't see how AP4600_SDK_API evaluates. You may need to specify the calling convention explicitly in your p/invoke. At present it uses the default, CallingConvention.StdCall .
  • The second argument is a modifiable buffer and so must be StringBuilder rather than `string.
  • The two size_t arguments should be pointer sized. Use UIntPtr .

So assuming the calling convention is StdCall it would be:

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

Call it like this:

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() 

The problem is explicitly stated in the error message that you received.

char *pTagDataBuf in c++ is not the same as string pTagDataBuf in c# for example. C# has managed strings. char* uses an unmanaged pointer. You may need to use an unsafe code block to access the function.

This error message will also show up if you are trying to load a 32bit dll into a 64bit project or vica verca.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM