简体   繁体   English

C ++ lib dll的C#包装器类

[英]C# wrapper class for c++ lib dll

I am trying to create a class in c# to access the function in a c++ lib. 我试图在c#中创建一个类,以访问c ++库中的函数。 The function in the c++ dll : C ++ dll中的函数:
bool WriteReply(const unsigned char *reply, const unsigned long reply_length) . bool WriteReply(const unsigned char *reply, const unsigned long reply_length)

A sample of how its used in c++:- 在C ++中如何使用的示例:-

unsigned short msg_id = 0x0000;                      
byte msg_body[] = {(byte)(GetTickCount()/0x100)};    // a random value for loopback data

    // combine the message id and message body into an big msg
    unsigned long msg_length = sizeof(msg_id)+sizeof(msg_body);
    byte* big_msg = new byte[msg_length];
    big_msg[0] = LOBYTE(msg_id);
    big_msg[1] = HIBYTE(msg_id);
    memcpy((void*)&big_msg[2], (void*)msg_body, sizeof(msg_body));

    // send the big message
    if (!big_dev.WriteReply(big_msg, msg_length))
    {
        //do something here
    }

I can't seem to pass the function from c# to the dll ( AccessViolationException ). 我似乎无法将函数从c#传递到dll( AccessViolationException )。 This is the command i've tried:- 这是我尝试过的命令:

byte[] bytearray = new byte[3] { 0x01, 0x02, 0x03 };
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytearray.Length);
Marshal.Copy(bytearray, 0, unmanagedPointer, bytearray.Length);

bool writestatus = (bool)NativeMethods.WriteReply(unmanagedPointer, (uint)bytearray.Length);

and on the import side:- 在进口方面:

[DllImport("dllname.dll", EntryPoint = "WriteReply")]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool WriteReply(IntPtr msg, uint reply_length);

Please let me know where have i gone wrong?Thanks! 请让我知道我在哪里出了问题?

Assuming your C++ method uses the string and does not modify it... 假设您的C ++方法使用字符串并且不修改它...

Try this 尝试这个

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply, const unsigned long reply_length);


[DllImport("libfile.dll", EntryPoint = "WriteReply")]
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString,
    [Out] UInt32 replyLength);

Or better yet (since C strings are null-terminated and the buffer is readonly, so you don't have to worry about buffer overflow, the length parameter is redudant): 或更好(由于C字符串以null终止并且缓冲区是只读的,因此您不必担心缓冲区溢出,length参数是多余的):

__declspec(dllexport) bool __cdecl WriteReply(const unsigned char *reply);


[DllImport("libfile.dll", EntryPoint = "WriteReply")]
private static extern bool WriteReplyExternal(
    [MarshalAs(UnmanagedType.LPStr)] [Out] string replyString);

These will work if the method is not within a class, otherwise you will need to use the C++ mangled name as the entry point . 如果该方法不在类之内,则这些方法将起作用,否则,您将需要使用C ++杂乱的名称作为入口点

If your string contains characters outside the 1...127 ASCII range (eg non-English letters), you should use wchar_t instead of char in the C++ and LPWStr instead of LPStr in the marshalling. 如果您的字符串包含1 ... 127 ASCII范围之外的字符(例如,非英语字母),则应在编组中使用wchar_t代替char,在C ++中使用LPWStr代替LPStr。

Edit: 编辑:

You need to wrap the private method with another method with a signature that is more appropriate for .NET eg 您需要将私有方法与具有更适合于.NET的签名的其他方法包装在一起,例如

public void WriteReply(string message)
{
    var result = WriteReplyExternal(message, message.Length);
    if (result == false)
        throw new ApplicationException("WriteReplay failed ...");
}

I think the latest addition of code provides a clue as to the real problem: 我认为最新添加的代码提供了有关实际问题的线索:

if (!big_dev.WriteReply(big_msg, msg_length))

This cannot work because WriteReply is an member function. 由于WriteReply是成员函数,因此无法工作。 You need to be calling a C style function rather than a C++ member function. 您需要调用C样式函数而不是C ++成员函数。 The latter requires an instance ( big_dev in the code sample). 后者需要一个实例(代码示例中的big_dev )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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