Pinvoke call всегда возвращает -1 - PullRequest
2 голосов
/ 29 июня 2011

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, я убрал функцию, чтобы просто вернуть значение int в качестве теста.

Я полностью озадачен и всемои чтения и поиска не оказываются полезными в решении этой проблемы.

Есть предложения?

Отредактировано для удаления ошибок копирования

Решение:

У меня произошла двукратная ошибка.С предложением снизу изменить возвращаемые значения с C ++ на INT_PTR и сменой платформы мне удалось получить вызов для возврата действительного дескриптора.

Большое спасибо за вашу помощь:)

1 Ответ

2 голосов
/ 29 июня 2011

Ваш код преобразует HANDLE в int. На 64-битных платформах это приведет к усечению и потере данных, поскольку HANDLE имеет ширину 64 бита, а int имеет ширину всего 32 бита. Компилятор должен был пометить это как минимум предупреждением.

Попробуйте вместо этого вернуть INT_PTR из OpenSerialConnection() (и соответственно измените тип возвращаемого значения оболочки C #).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...