一直都觉得c#调用c++dll这块很麻烦,不过要用也没办法。刚开始类型转换头疼了一阵,不过也都解决了,今天遇到的这个问题,是怎么都过不去了,希望大家指点指点!
C++原型:
struct SipClient
{
char * realm;
void * lpvoid;
char * from_ip;
int from_port;
char * to_ip;
int to_port;
char * client_id;
char * server_id; //平台编码
int reg_count;
SipClient(){memset(this, 0, sizeof(SipClient));}
~SipClient()
{
delete[] from_ip;
delete[] realm;
delete[] client_id;
delete[] to_ip;
delete[] server_id;
}
};
SIPCLIENT_API SipClient* SCInit(const char * reaml, const char * from_ip, int from_port, const char * to_ip, int to_port, const char * server_id, const char * user_id, const char * user_name, void * user_obj_param);
C#里是这么些的
public struct SipClient
{
public string realm; //鉴权码
public IntPtr lpvoid; //用户参数
public string from_ip; //本地IP
public int from_port; //本地端口
public string to_ip; //SIP服务器IP
public int to_port; //SIP服务器端口
public string client_id; //用户的编码
public string server_id; //SIP服务器的编码
public int reg_id; //保留,暂不使用
}
[DllImport("sipclient.dll")]
public static extern SipClient SCInit(string reaml, string from_ip, int from_port,
string to_ip, int to_port, string server_id,
string user_id, string user_name, IntPtr user_obj_param);//函数调用private const string USER_ID = "180400000090000000";
private const string SERVER_ID = "180400000099000000";SIPCLIENT_API.SCInit("192.168.10.23", "192.168.10.32", 5092, "192.168.10.23", 5090, SERVER_ID, USER_ID, USER_ID, IntPtr.Zero);
黄色标记处写作SipClient时,运行时函数调用异常:
Additional information: 方法的类型签名与 PInvoke 不兼容。
想按照网上一种做法,将SipClient改为IntPtr,运行时还是出错,不过异常是:
Additional information: 无法在 DLL“sipclient.dll”中找到名为“SCInit”的入口点。
我能够想到的办法都用了,还是不能解决这些问题,期待大家的回答!
用 DEPENDS.EXE 查看你的 sipclient.dll 中的函数的导出名称,它有可能的名称是 SCInitXAjlkjsaldjaslkd.
生成 C++ DLL的时候,用 extern "C" 导出函数名称,则可以避免编译器为你自动生成的名称。
调用成功后,你可以用 Marshal.PtrToStructure 把 IntPtr 转换成你的 SipClient。
用.def 模块定义文件,定义导出函数的名称。
确保C#编译出来的EXE和你的DLL都是32位或者64位的。
mixed 的exe会自动识别和提升intptr的长度,在32位系统下是32位的,在64位系统下是64位的,针对这个,需要做两个DLL,一个32位,一个64位。
那C#程序在调用64位的DLL时,需要具体注意些什么呢