C#调用C/C++ DLL 参数传递和回调函数的总结

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#调用C/C++ DLL 参数传递和回调函数的总结相关的知识,希望对你有一定的参考价值。

原文:C#调用C/C++ DLL 参数传递和回调函数的总结

Int型传入:

Dll端:

extern?"C"?__declspec(dllexport)?int?Add(int?a,?int?b)

{

????return?a+b;

}

C#端:

[DllImport("aeClient2.0.dll",?CallingConvention?=CallingConvention.Cdecl)]

?public?static?extern?unsafe?int?Add(int?a,?int?b);

?

Int型传入传出:

Dll端:

extern?"C"?__declspec(dllexport)?int?Add(int?*a,?int*?b)

{

??? *a?= 2;

??? *b?= 3;

????return?add(2, 3);

}

C#端

[DllImport("aeClient2.0.dll",?CallingConvention?=CallingConvention.Cdecl)]

?public?static?extern?unsafe?int?Add(int?a,?int?b);

?

String传入:

Dll端:

extern?"C"?__declspec(dllexport)?BOOL?sendMessage(char*?msg)

{

????CString?str?=?msg;

??? ::AfxMessageBox(str.GetBuffer(0));

????return?3;

}

C#端:

[DllImport("aeClient1.1.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?int?sendMessage(string?msg);

?

string?strin?=?"llqqttt??";

sendMessage(strin);

?

String型传入传出:

Dll端:

extern?"C"?__declspec(dllexport)?BOOL?GetErrorMessage(char?*szErrorMessage?)

{

????CString?str?=?szErrorMessage;

????AfxMessageBox(str);

????char?tmp[] =?"nm世界和平nmnm";

????strcpy(szErrorMessage,tmp);

????return?3;

}

C#端:

[DllImport("aeClient1.1.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?int?GetErrorMessage(StringBuilder?msg);

?

StringBuilder?buf?=?new?StringBuilder(1024);//指定的buf大小必须大于传入的字符长度

buf.Append("abc中国人");

int?outdata?=?GetErrorMessage(buf, 1);?

string?strout?=?buf.ToString();

?

结构体传入:

Dll端:

class?NET_INFO_STRUCT?

{?

public:

????DWORD?nDurationTime;?//??o?à???

????double?nReceiveByte;?//¨?o?á?¨2?

????double?nSendByte;???//¤?é¨aá?¨2?

????WORD?word;

????char?buf[200];

????FILETIME?time;

};

extern?"C"?__declspec(dllexport)?BOOL?NetGetConnectDetail(NET_INFO_STRUCT?lpNetInfo)

{

??? ::AfxMessageBox(lpNetInfo.buf);

????return?3;

}

?

C#端

public?struct?FILETIME

??? {

????????public?uint?high;

????????public?uint?low;

??? }

????public?struct?NET_INFO_STRUCT?

??? {?

????????public?uint?nDurationTime;?//??o?à???

????????public?double?nReceiveByte;?//¨?o?á?¨2?

????????public?double?nSendByte;???//¤?é¨aá?¨2?

????????public?ushort?ush;

??????? [MarshalAs(UnmanagedType.ByValTStr,?SizeConst?= 200)]

????????public?string?str;

????????public?FILETIME?time;

??? } ;

[DllImport("aeClient1.1.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?unsafe?int?NetGetConnectDetail(NET_INFO_STRUCT?lpNetInfo);

?

NET_INFO_STRUCT?stru?=?new?NET_INFO_STRUCT();

????????????stru.nDurationTime?= 8989;

????????????stru.nReceiveByte?= 89.89;

????????????stru.nSendByte?= 89.8900;

????????????stru.ush?= 56;

????????????stru.str?=?"来来去去ypfisja";

????????????stru.time.high?= 24;

????????????stru.time.low?= 17;

????????????NetGetConnectDetail(stru);

?

?

结构体数组传出:

Dll端:

struct?UIM_BOOK_STRUCT?

{?

????int?UimIndex;?

????char?szName[15];?

????char?szPhone[21];?

};?

extern?"C"?__declspec(dllexport)?int?ReadUimAllBook(UIM_BOOK_STRUCT?lpUimBookItem[],intnMaxArraySize)

{

????lpUimBookItem[0].UimIndex?= 345;

????strcpy(lpUimBookItem[0].szName?,?"dsd");

????strcpy(lpUimBookItem[0].szPhone?,?"bbbb");

?

????lpUimBookItem[1].UimIndex?= 111;

????strcpy(lpUimBookItem[1].szName?,?"ddddd");

????strcpy(lpUimBookItem[1].szPhone?,?"vvvvvv");

?

????lpUimBookItem[2].UimIndex?= 2222;

????strcpy(lpUimBookItem[2].szName?,?"d3343434sd");

????strcpy(lpUimBookItem[2].szPhone?,?"bbbfggfggggfgb");

?

????return?4;

}

C#端:

[StructLayout(LayoutKind.Sequential,?CharSet?=?CharSet.Ansi)]

public?struct?UIM_BOOK_STRUCT

{

????????public?int?UimIndex;

??????? [MarshalAs(UnmanagedType.ByValTStr,?SizeConst?= 15)]

????????public?string?szName;

??????? [MarshalAs(UnmanagedType.ByValTStr,?SizeConst?= 21)]

????????public?string?szPhone;

};

[DllImport("aeClient1.1.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?unsafe?int?ReadUimAllBook([Out]?UIM_BOOK_STRUCT[]?lpUimBookItem,?intnMaxArraySize);

?

UIM_BOOK_STRUCT[]?p?=?new?UIM_BOOK_STRUCT[20];

int?rets?=?ReadUimAllBook(p,?p.Length);

?

回调函数传递字符串:

Dll端:

typedef?int?(*pfCallBack)(int?a,?char?b[]);

pfCallBack?CallBackfun?=?NULL;

?

extern?"C"?__declspec(dllexport)?void?SetCB(int?(*pfCallBack)(int?a,?charb[]))?

{?

????CallBackfun?=?pfCallBack;?

}?

char?ch[100];

extern?"C"?__declspec(dllexport)?void?callTheCB()

{

????int?a?= 4;

????memset(ch,?‘‘, 100);

????strcpy(ch,?"aabbcc");

????CallBackfun(a,?ch);

}

C#端

//定?§义°?一°?个?委?¥托aD,ê?其?返¤|ì回?类¤¨¤型¨a和¨a形?参?与??方¤?法¤?§体??的ì?返¤|ì回?类¤¨¤型¨a形?参?一°?致??

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]//一°?定?§要°a加¨?上|?这a句?,ê?要°a不?然¨?C#中D的ì?回?调ì??函?¥数oy只?要°a被à?调ì??用??一°?次??,ê?程¨?序¨°就¨a异°¨?常?ê退a?出?了¢?!ê?!ê?!ê??

public?delegate?int?callBackHandler(int?a, [MarshalAs(UnmanagedType.LPStr)]StringBuilder?b);

callBackHandler?fun;//声|¨′明??一°?个?委?¥托aD变à?量¢??

[DllImport("xxx.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?unsafe?void?SetCB(callBackHandler?fun1);

[DllImport("xxx.dll",?CallingConvention?=CallingConvention.Cdecl)]

public?static?extern?unsafe?void?callTheCB();

?

int?localFun(int?a, [MarshalAs(UnmanagedType.LPStr)]StringBuilder?b)

{

????????MessageBox.Show(b.ToString());

????????return?0;

}

?

fun?=?new?callBackHandler(localFun);//给?委?¥托aD变à?量¢?赋3值|ì???

SetCB(fun);//用??委?¥托aD当ì?à做á?函?¥数oy指?针?作á??为a参?数oy传??入¨?

callTheCB();

?

回调函数传递结构体:

Dll端:

struct?REvent

{

????REvent(ONEVENTSTRUCT*?pEVENTSTRUCT);

????WORD????m_ChangeMask;

????WORD????m_State;

????char?m_Source[200];

};

?

typedef?void?(*pfCallBackEvent)(REvent?eve/*, char m_Source[]*/);

pfCallBackEvent?CallBackfunEvent?=?NULL;

extern?"C"?__declspec(dllexport)?void?SetCBEvent(void?(*pfCallBackEvent)(REvent?eve/*, char m_Source[]*/))?

{

????CallBackfunEvent?=?pfCallBackEvent;?

}?

void?callCBEvent(REvent?eve/*, char m_Source[]*/)

{

????CallBackfunEvent(eve/*, m_Source*/);

}

?

//调用回调函数

callCBEvent(*pREvent/*, pEvent->m_Message.GetBuffer(0)*/);

C#端:

[StructLayout(LayoutKind.Sequential,?CharSet?=?CharSet.Ansi)]

????????public?struct?REvent

????????{

????????????public?ushort?m_ChangeMask;

????????????public?ushort?m_State;

????????????[MarshalAs(UnmanagedType.ByValTStr,?SizeConst?= 200)]

????????????public?string?m_Source;

????????};

?

????????[StructLayout(LayoutKind.Sequential,?CharSet?=?CharSet.Ansi)]//可¨|以°?指?定?§编ਤ码?类¤¨¤型¨a

????????public?struct?EventSourceTag

????????{

????????????//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]

????????public?IntPtr?name;

????????};

????????//定?§义°?一°?个?委?¥托aD,ê?其?返¤|ì回?类¤¨¤型¨a和¨a形?参?与??方¤?法¤?§体??的ì?返¤|ì回?类¤¨¤型¨a形?参?一°?致??

????????[UnmanagedFunctionPointer(CallingConvention.Cdecl,?CharSet?=?CharSet.Ansi)]//一°?定?§要°a加¨?上|?这a句?,ê?要°a不?然¨?C#中D的ì?回?调ì??函?¥数oy只?要°a被à?调ì??用??一°?次??,ê?程¨?序¨°就¨a异°¨?常?ê退a?出?了¢?!ê?!ê?!ê?

????????public?delegate?void?CBEventHandle(REvent?eve/*, [MarshalAs(UnmanagedType.LPStr)]StringBuilder source*/);

????????CBEventHandle?cbFun;//声|¨′明??一°?个?委?¥托aD变à?量¢??

????????[DllImport("xxx.dll",?CharSet?=?CharSet.Ansi,?CallingConvention?=?CallingConvention.Cdecl)]

????????public?static?extern?unsafe?void?SetCBEvent(CBEventHandle?fun);

?

void?CBEvent(REvent?eve/*, [MarshalAs(UnmanagedType.LPStr)]StringBuilder source*/)

{

????????//string str = Marshal.PtrToStringAnsi(source);

????????//string str = System.Text.Encoding.Default.GetString(source);

????????MessageBox.Show(eve.m_Message.ToString());

}

?

cbFun?=?new?CBEventHandle(CBEvent);

SetCBEvent(cbFun);



以上是关于C#调用C/C++ DLL 参数传递和回调函数的总结的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C# 调用具有 void* 回调和对象参数的 C++ Dll 中的函数

DELPHI调用DLL时的回调函数问题

将带有参数的 c# 回调方法传递给 c++ dll 会导致 System.ExecutionEngineException

c#调用c++的DLL,接口函数参数有函数指针,在线等解决办法

C#中调用C的DLL中的回调函数,想实现消息响应机制

C语言的回调函数