Pinvoke调用始终返回-1

时间:2011-06-29 12:49:57

标签: 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);

句柄是IntPtr的调用:

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

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

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

有什么建议吗?

已编辑以删除复制错误

解决方案:

我发生了两次错误。根据下面的建议将返回值从C ++更改为INT_PTR并进行平台更​​改,我能够调用返回有效句柄。

非常感谢您的所有帮助:)

1 个答案:

答案 0 :(得分:2)

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

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