1

我正在尝试在 c# 中创建一个类来访问 c++ 库中的函数。c++ dll 中的函数:
bool WriteReply(const unsigned char *reply, const unsigned long reply_length).

如何在 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
    }

我似乎无法将函数从 c# 传递给 dll ( AccessViolationException)。这是我尝试过的命令:-

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

在进口方面:-

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

请让我知道我哪里出错了?谢谢!

4

2 回答 2

0

假设您的 C++ 方法使用字符串并且不修改它...

尝试这个

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

或者更好(因为 C 字符串是空终止的并且缓冲区是只读的,所以你不必担心缓冲区溢出,长度参数是多余的):

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

如果方法不在类中,这些将起作用,否则您将需要使用 C++ 错位名称作为入口点

如果您的字符串包含 1...127 ASCII 范围之外的字符(例如非英文字母),您应该在 C++ 中使用 wchar_t 而不是 char,在编组中使用 LPWStr 而不是 LPStr。

编辑:

您需要使用另一种方法包装私有方法,该方法具有更适合 .NET 的签名,例如

public void WriteReply(string message)
{
    var result = WriteReplyExternal(message, message.Length);
    if (result == false)
        throw new ApplicationException("WriteReplay failed ...");
}
于 2012-04-29T11:14:17.103 回答
0

我认为最新添加的代码为真正的问题提供了线索:

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

这不能工作,因为WriteReply它是一个成员函数。您需要调用 C 样式函数而不是 C++ 成员函数。后者需要一个实例(big_dev在代码示例中)。

于 2012-04-30T11:47:45.077 回答