c# - Pinvoke 调用总是返回 -1

标签 c# .net sdk pinvoke

Visual Studio 2005.NET SDK 2.0

我们需要包装旧的 C++ 函数来打开内部和外部端口的句柄(C# 方法对我们的处理器来说开销太大)

这是原始的 C++ 函数:

extern "C" SERIALLIB_API HANDLE
OpenSerialConnection(TCHAR *port, int baudRate, int parity, int dataBits, int stopBits)
{
    // Open the serial device file driver
    HANDLE hSerial = CreateFile(port,
        GENERIC_READ | GENERIC_WRITE,
        0,    // must be opened with exclusive-access
        NULL, // default security attributes
        OPEN_EXISTING, // must use OPEN_EXISTING
        0,    // overlapped I/O not supported
        NULL  // hTemplate must be NULL for comm devices
        );

RETAILMSG(1, (TEXT("Handle %d\n"),hSerial));

// Ensure the handle opened correctly
if (hSerial == INVALID_HANDLE_VALUE)
{
    RETAILMSG(1, (TEXT("INVALID HANDLE #1\n")));
    return INVALID_HANDLE_VALUE;
}

// Set the handle to report only when there's
// a character to receive or when the transmit
// buffer is empty
if (!SetCommMask(hSerial, EV_RXCHAR|EV_TXEMPTY))
{
    CloseHandle(hSerial);
    RETAILMSG(1, (TEXT("INVALID HANDLE #2\n")));
    return INVALID_HANDLE_VALUE;
}

// The handle will now be configured to be the requested
// serial interface. The current settings are retrieved,
// and only the necessary settings are changed.
DCB dcb;
ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);

BOOL fSuccess = GetCommState(hSerial, &dcb);
if (!fSuccess) 
{
    CloseHandle(hSerial);
    RETAILMSG(1, (TEXT("INVALID HANDLE #3\n")));
    return INVALID_HANDLE_VALUE;
}

// Fill in DCB with the desired settings
dcb.BaudRate = baudRate;   // set the baud rate
dcb.ByteSize = 8;             // data size, xmit, and rcv
dcb.Parity = parity;        // no parity bit
dcb.StopBits = stopBits;    // one stop bit

// Set the timeout values to make reading a synchronous activity.
// Reading from the serial line takes place in a separate thread,
// so this is what we want.
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout = MAXDWORD;
timeout.ReadTotalTimeoutConstant = MAXDWORD - 1;
timeout.ReadTotalTimeoutMultiplier = MAXDWORD;
timeout.WriteTotalTimeoutConstant = 0;
timeout.WriteTotalTimeoutMultiplier = 0;

if (!SetCommTimeouts(hSerial, &timeout) ||
    !SetCommState(hSerial, &dcb))
{
    CloseHandle(hSerial);
    RETAILMSG(1, (TEXT("INVALID HANDLE #4\n")));
    return INVALID_HANDLE_VALUE;
}

return hSerial;
}

C# 包装器:

[DllImport("SerialLib.dll")]
    public static extern IntPtr OpenSerialConnection(string port, int baudRate, int parity, int dataBits, int stopBits);

handle 是 IntPtr 的调用:

handle = Unmanaged.SerialWrapper.OpenSerialConnection(portName,
                                                                  baudRate,
                                                                  parityToInt(parity),
                                                                  dataBits,
                                                                  stopBitsToInt(stopBits));

无论我在 OpenSerialConnection C++ 代码中有什么,handle 的值总是以 -1 返回,我已剥离该函数以仅返回 4 的 int 值作为测试。

我完全被难住了,我所有的阅读和搜索都证明对解决这个问题没有帮助。

有什么建议吗?

编辑以消除复制错误

解决方案:

我有一个双重错误。根据下面的建议,将返回值从 C++ 更改为 INT_PTR 以及平台更改,我能够获得返回有效句柄的调用。

非常感谢您的帮助:)

最佳答案

您的代码正在将 HANDLE 转换为 int。在 64 位平台上,这将导致截断和数据丢失,因为 HANDLE 是 64 位宽而 int 只有 32 位宽。编译器应该(至少)用警告标记它。

尝试从 OpenSerialConnection() 返回一个 INT_PTR(并相应地更改 C# 包装器的返回类型)。

关于c# - Pinvoke 调用总是返回 -1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6520891/

相关文章:

C# 使用 Powershell.AddParameter 有两个条件

javascript - AJAX PageMethods 与路由冲突?

go - Go SDK使用的Gcloud身份验证帐户

Android SDK - 不在触摸中心缩放

C# WPF 设置焦点 TabItem

c# - 按特定顺序获取所有文件夹

c# - 确定 List<T> 中的值跳跃

c# - 列表的 XML 序列化

C#:如何设置 DNS 解析超时?

ios - 找不到 Accella Mobile SDK IOS