вызов Win32 DLL API из приложения C # - PullRequest
0 голосов
/ 21 декабря 2009

Я создал win32 dll, которая отправляет и получает пакеты данных ssl с нашего сервера, я вызываю функцию dll, используя механизм P / Invoke, из моего приложения C #, которое выполняет все необходимые задачи.

Когда я звоню Connect (char * lpPostData)

и я использую статический массив char postData [] в качестве запроса на публикацию, он работает нормально, если я использую char * lpPostData в качестве параметра отправки из моего приложения C # для отправки запроса, он не работает. Это что-то с преобразованием строки C # в char * ?? если это так, как мне это сделать? Как отладить в Win32 dll ???

Вызов экспортированной функции из приложения C #:

[DllImport("testdllwm6.dll", EntryPoint = "Connect")]   public
static extern int pConnect(string postdata);

string postdata="<SyncML><SyncHdr><VerDTD>1.2</VerDTD><VerProto>SyncML/1.2</VerProto><SessionID>33622878</SessionID><MsgID>1</MsgID><Target><LocURI>http://sync.com</LocURI></Target><Source><LocURI>IMEI::358997011403172</LocURI><LocName>syncfdg</LocName></Source><Meta><MaxMsgSize
xmlns=\"syncml:metinf\">10000</MaxMsgSize></Meta></SyncHdr><SyncBody><Alert><CmdID>1</CmdID><Data>201</Data><Item><Target><LocURI>contacts</LocURI></Target><Source><LocURI>./contacts</LocURI></Source><Meta><Anchor
xmlns=\"syncml:metinf\"><Last>000000T000000Z</Last><Next>20091125T122400Z</Next></Anchor></Meta></Item></Alert><Final></Final></SyncBody></SyncML>";

int j = pConnect(postdata);

Декларация:

__declspec(dllexport) int Connect(char* lpPostData);

Функция определяется как:

__declspec(dllexport) int Connect(char* lpPostData) {

LPCTSTR lpszAgent = _T("CeHttp"); 
DWORD dwError;   DWORD sizeInResult,
sizeOutResult, sizeToWrite,
sizeWritten,dwRead;   HINTERNET
hInternet=NULL;   HINTERNET
hConnect=NULL;  HINTERNET
hRequest=NULL;  LPDWORD
pSizeInResult = &sizeInResult;
LPDWORD pSizeOutResult = &sizeOutResult;
LPDWORD pSizeToWrite = &sizeToWrite;
LPDWORD pSizeWritten = &sizeWritten;  int read = 0;


char postData[637]
="<SyncML><SyncHdr><VerDTD>1.2</VerDTD><VerProto>SyncML/1.2</VerProto><SessionID>66622878</SessionID><MsgID>1</MsgID><Target><LocURI>http://sync.com</LocURI></Target><Source><LocURI>IMEI::358997011403172</LocURI><LocName>new123</LocName></Source><Meta><MaxMsgSize
xmlns=\"syncml:metinf\">10000</MaxMsgSize></Meta></SyncHdr><SyncBody><Alert><CmdID>1</CmdID><Data>201</Data><Item><Target><LocURI>contacts</LocURI></Target><Source><LocURI>./contacts</LocURI></Source><Meta><Anchor
xmlns=\"syncml:metinf\"><Last>000000T000000Z</Last><Next>20091125T122400Z</Next></Anchor></Meta></Item></Alert><Final></Final></SyncBody></SyncML>";
LPCWSTR lpszHeaders =_T("Content-Type: application/vnd.sync+xml");  
BOOL bResult; 

if(!HttpSendRequest(hRequest,lpszHeaders,wcslen(lpszHeaders),
                    lpPostData,strlen(lpPostData)))
{

    dwError = GetLastError();  
    printf(" not HttpSendRequest");  
    return read;
}

return read;

Ответы [ 5 ]

1 голос
/ 21 декабря 2009

Точка отказа очень очевидна. Windows CE - это Юникод. Строка в C # является массивом широких символов, символ char [] в C является многобайтовым. Вы смешиваете два, и это плохо, плохо, плохо.

Я имею в виду, что вы смешиваете их в одном вызове, отправляете широкие заголовки и многобайтовые postData в HttpSendRequest? Это, конечно, не может быть правдой.

Измените функцию подключения, чтобы она выглядела следующим образом:

int Connect(TCHAR* lpPostData) 

попробуйте еще раз и вернитесь с результатами.

Конечно, это также означает, что вам также нужно изменить и вызов strlen.

В качестве примечания, я не понимаю, почему вы все равно должны вызывать C ++ для этого вызова. Вы можете сделать это прямо из своего приложения на C #.

0 голосов
/ 21 декабря 2009

Вам необходимо добавить атрибут MarshalAs к строковому параметру, чтобы среда выполнения .NET знала, как его упорядочить; по умолчанию строки маршалируются как Unicode, но вы хотите ANSI:

[DllImport("testdllwm6.dll", EntryPoint="Connect")]
public static extern int Connect([MarshalAs(UnmanagedType.LPStr)] string lpPostData);
0 голосов
/ 21 декабря 2009

Это что-то с преобразованием строки C # в char * ??

CharSet по умолчанию, используемый .Net Interop Marshaler, - это Ansi.

Если вы хотите использовать параметры Unicode (LPCWSTR), Вы можете попробовать:

[DllImport("testdllwm6.dll", EntryPoint = "Connect", CharSet=CharSet.Unicode)] 
public static extern int pConnect(string postdata);

Кстати, вы можете обратиться к .NET 2.0 Рецепты взаимодействия: подход к решению проблемы для получения дополнительной информации.

0 голосов
/ 21 декабря 2009

использование

System.Text.StringBuilder

передать это вашей функции

0 голосов
/ 21 декабря 2009

кажется, что dll является расширением MFC dll, возможно, может быть вызвано только приложением MFC. я не уверен.

...