从C#应用程序调用win32 dll api

时间:2009-12-21 12:52:09

标签: c# windows windows-mobile

我创建了一个win32 dll,它从我们的服务器发送和接收ssl数据包,我正在使用来自我的C#app的P / Invoke机制调用一个dll函数,它执行所有必要的任务。

当我调用Connect(char * lpPostData)

函数和我使用静态char postData []数组作为发布请求它工作正常,如果我使用char * lpPostData作为我的C#app的发送参数发布请求它不起作用。是否将C#字符串转换为char *?如果是这样的话我该怎么做?如何调试Win32 dll ???

从C#app调用导出的函数:

[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 个答案:

答案 0 :(得分:1)

失败点非常明显。 Windows CE是Unicode。 C#中的字符串是宽字符数组,C中的char []是多字节数组。你把两者混合在一起,那就是坏,坏,坏。

我的意思是你在同一个调用中混合它们,向HttpSendRequest发送宽标头和多字节postData?这肯定是不对的。

将Connect功能更改为如下所示:

int Connect(TCHAR* lpPostData) 

再试一次,然后回来看结果。

当然这也意味着您还需要更改strlen调用。

作为旁注,我不明白你为什么要为这个电话打电话给C ++。你可以直接从你的C#应用​​程序中完成。

答案 1 :(得分:0)

似乎dll是MFC扩展dll,也许只能通过MFC应用程序进行callec。我不确定。

答案 2 :(得分:0)

  

是否将C#字符串转换为char * ??

.Net Interop Marshaler使用的默认CharSet是Ansi。

如果要使用Unicode(LPCWSTR)参数, 你可以尝试:

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

BTW,你可以参考.Net 2.0 Interoperability Recipes: A Problem-Solution Approach 了解更多信息。

答案 3 :(得分:0)

您需要将MarshalAs属性添加到字符串参数中,以便.NET运行时知道如何编组它;默认情况下,字符串被编组为Unicode,但您需要ANSI:

[DllImport("testdllwm6.dll", EntryPoint="Connect")]
public static extern int Connect([MarshalAs(UnmanagedType.LPStr)] string lpPostData);

答案 4 :(得分:-1)

使用

System.Text.StringBuilder

将其传递给您的函数