C#调用C/C++ DLL的相关说明
C# 調(diào)用DLL 常用如下方式來引用庫中的函數(shù) (當(dāng)然還有很多其它的實(shí)現(xiàn)方式,這里就不多講),本文主要講要使用中遇到的常見問題:
一,庫的引用 加上 :using System.Runtime.InteropServices;
[DllImport("XXX")]
static extern void UbtServoGroupInit(ref UbtUartServo Sgroup, pwrite write, pread read);
上面有注意的有兩點(diǎn):
1,XXX 可以是DLL庫名不帶.dll 后輟,也可以是全名
2,函數(shù)前的 static extern 是一定要加的
?
二,DLL頭文件實(shí)現(xiàn)
C#中沒有.H文件,如果DLL中用到了一些頭文件(里面有結(jié)構(gòu)體等自定義類型),需在要C#環(huán)境中從新定義,這里會有各種變量的對應(yīng)轉(zhuǎn)換關(guān)系:
/****** 以下內(nèi)容引自于https://www.cnblogs.com/zhaoxinshanwei/p/4008627.html? ***********/
//c++:HANDLE(void???*)???????----???c#:System.IntPtr????????
//c++:Byte(unsigned???char)???----????c#:System.Byte?????????
//c++:SHORT(short)???????????----????c#:System.Int16?????????
//c++:WORD(unsigned?short)?---??c#:System.UInt16????????
//c++:INT(int)?????????????????----????c#:System.Int16????????
//c++:INT(int)??????????????????----????c#:System.Int32?????????
//c++:UINT(unsigned?int)??----????c#:System.UInt16????????
//c++:UINT(unsigned?int)?----????c#:System.UInt32????????
//c++:LONG(long)?????????????----????c#:System.Int32?????????
//c++:ULONG(unsigned?long)?--???c#:System.UInt32?????????
//c++:DWORD(unsigned?long)?--??c#:System.UInt32?????????
//c++:DECIMAL?????????----????c#:System.Decimal?????????
//c++:BOOL(long)????????----????c#:System.Boolean?????????
//c++:CHAR(char)???????----????c#:System.Char??
???????
//c++:LPSTR(char?*)??????----????c#:System.String?????????
//c++:LPWSTR(wchar_t?*)??----????c#:System.String?????????
//c++:LPCSTR(const?char?*)??---???c#:System.String?????????
//c++:LPCWSTR(const?wchar_t?*)?---???c#:System.String?????????
//c++:PCAHR(char?*)???----???c#:System.String?????
????
//c++:BSTR???????----????c#:System.String???????
??
//c++:FLOAT(float)??????----????c#:System.Single?????????
//c++:DOUBLE(double)????----????c#:System.Double?????????
//c++:VARIANT???????????----????c#:System.Object?????????
//c++:PBYTE(byte???*)???----????c#:System.Byte[]?????????
//c++:BSTR??????----????c#:StringBuilder????
????
//c++:LPCTSTR???----????c#:StringBuilder??
??????
//c++:LPCTSTR???----????c#:string????????
//c++:LPTSTR????----????
c#:[MarshalAs(UnmanagedType.LPTStr)]?string??
???????
//c++:LPTSTR?????----????c#:StringBuilder?
?????
//c++:LPCWSTR???----????c#:IntPtr????????
//c++:BOOL??????----????c#:bool???????????
//c++:HMODULE???----????c#:IntPtr????????
????
//c++:HINSTANCE?----????c#:IntPtr????????
?
//c++:結(jié)構(gòu)體????----????c#:public?struct?結(jié)構(gòu)體{};?
????????
//c++:結(jié)構(gòu)體?**變量名???----????c#:out?變量名???
//C#中提前申明一個結(jié)構(gòu)體實(shí)例化后的變量名??????
?
//c++:結(jié)構(gòu)體?&變量名????----????c#:ref?結(jié)構(gòu)體?變量名?????????????????
//c++:WORD??????----????c#:ushort????????
//c++:DWORD?????----????c#:uint????????
//c++:DWORD?????----????c#:int????????
//c++:UCHAR?????----????c#:int????????
//c++:UCHAR?????----????c#:byte????????
//c++:UCHAR*????----????c#:string??????
??
//c++:UCHAR*????----????c#:IntPtr????????
//c++:GUID??????----????c#:Guid????????
//c++:Handle????----????c#:IntPtr????????
//c++:HWND??????----????c#:IntPtr????????
//c++:DWORD?????----????c#:int????????
//c++:COLORREF??----????c#:uint???????
?
//c++:unsigned?char?????----????c#:byte??????
??
//c++:unsigned?char?*???----????c#:ref?byte???????
?
//c++:unsigned?char?*???----????
c#:[MarshalAs(UnmanagedType.LPArray)]?byte[]????????
//c++:unsigned?char?*???----????
c#:[MarshalAs(UnmanagedType.LPArray)]?Intptr????????
//c++:unsigned?char?&???----????c#:ref?byte??
??????
//c++:unsigned?char?變量名??????----????c#:byte?變量名????????
//c++:unsigned?short?變量名????----???c#:ushort?變量名????????
//c++:unsigned?int?變量名???????----????c#:uint?變量名????????
//c++:unsigned?long?變量名?????----????c#:ulong?變量名????????
//c++:char?變量名???????----????c#:byte?變量名?
??
//c++中一個字符用一個字節(jié)表示,c#中一個字符用兩個字節(jié)表示????????
//c++:char?數(shù)組名[數(shù)組大小]?????----????
c#:MarshalAs(UnmanagedType.ByValTStr,?SizeConst?=?數(shù)組大小)]????????
???
//c++:char?*????????????----????c#:string???????
?
//c++:char?*????????????----????c#:StringBuilder
????
//c++:char?*變量名??????----????c#:ref?string?變量名????????
//c++:char?*輸入變量名??----????c#:string?輸入變量名????????
//c++:char?*輸出變量名??----????
c#:[MarshalAs(UnmanagedType.LPStr)]?StringBuilder?輸出變量名??????
??
//c++:char?**???????????----????c#:string?????
???
//c++:char?**變量名?????----????c#:ref?string?變量名????????
//c++:const?char?*??????----????c#:string???
?????
//c++:char[]????????????----????c#:string?????
???
//c++:char?變量名[數(shù)組大小]?????----????
c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=數(shù)組大小)]?public?string?變量名;?????
//c++:struct?結(jié)構(gòu)體名?*變量名???----????c#:ref?結(jié)構(gòu)體名?變量名????????
//c++:委托?變量名???----????c#:委托?變量名????
????
//c++:int???????----????c#:int????????
//c++:int???????----????c#:ref?int????????
//c++:int?&?????----????c#:ref?int??????
??
//c++:int?*?????----????c#:ref?int??????
//C#中調(diào)用前需定義int?變量名?=?0;??????
??
//c++:*int??????----????c#:IntPtr????????
//c++:int32?PIPTR?*?????----????c#:int32[]???
?????
//c++:float?PIPTR?*?????----????c#:float[]???????
?????????
//c++:double**?數(shù)組名??????????----????c#:ref?double?數(shù)組名????????
//c++:double*[]?數(shù)組名??????????----????c#:ref?double?數(shù)組名????????
//c++:long??????????----????c#:int????????
//c++:ulong?????????----????c#:int???????????
?????
//c++:UINT8?*???????----????c#:ref?byte??????
?
//C#中調(diào)用前需定義byte?變量名?=?new?byte();????????????????
//c++:handle????----????c#:IntPtr????????
//c++:hwnd??????----????c#:IntPtr?????????
???????????????
//c++:void?*????----????c#:IntPtr??????????
??????
//c++:void?*?user_obj_param????----????
c#:IntPtr?user_obj_param????????
//c++:void?*?對象名稱????----????
c#:([MarshalAs(UnmanagedType.AsAny)]Object?對象名稱????????????????
//c++:char,INT8,SBYTE,CHAR??--??c#:System.SByte??????????
//c++:short,?short?int,?INT16,?SHORT????????????????????????----????c#:System.Int16????????
??
//c++:int,?long,?long?int,INT32,?LONG32,?BOOL?,?INT??----????c#:System.Int32???????
???
//c++:__int64,INT64,LONGLONG???????????????????????????--??c#:System.Int64??????????
//c++:unsigned?char,?UINT8,?UCHAR?,?BYTE???????????????----????c#:System.Byte??????????
//c++:unsigned?short,?UINT16,?USHORT,?WORD,?ATOM,?WCHAR?,?__wchar_t??----??c#:System.UInt16??????????
//c++:unsigned,?unsigned?int,?UINT32,?ULONG32,?DWORD32,?ULONG,?DWORD,?UINT?????
?----????c#:System.UInt32??????????
//c++:unsigned?__int64,?UINT64,?DWORDLONG,?ULONGLONG????????????????????????????
----????c#:System.UInt64??????????
//c++:float,FLOAT????--??c#:System.Single??????????
//c++:double,?long?double,?DOUBLE??????????????????????????----????c#:System.Double??????????
//Win32?Types????????----??CLR?Type???????
???????????
//Struct需要在C#里重新定義一個Struct????
????
//CallBack回調(diào)函數(shù)需要封裝在一個委托里,delegate?static?extern?int?FunCallBack(string?str);???????
?
//unsigned?char**?ppImage替換成IntPtr?ppImage????????
//int&?nWidth替換成ref?int?nWidth???????
?
//int*,?int&,?則都可用?ref?int?對應(yīng)??????
??
//雙針指類型參數(shù),可以用?ref?IntPtr???????
?
//函數(shù)指針使用c++:?typedef?double?(*fun_type1)(double);?對應(yīng)?c#:public?delegate?double??fun_type1(double);????????
//char*?的操作c++:?char*;?對應(yīng)?c#:StringBuilder;????????
//c#中使用指針:在需要使用指針的地方?加?unsafe????????
//unsigned???char對應(yīng)public???byte???
/****** 以上內(nèi)容引自于https://www.cnblogs.com/zhaoxinshanwei/p/4008627.html? ***********/
根據(jù)上面的對應(yīng)關(guān)系重新實(shí)現(xiàn)結(jié)構(gòu)體或自定義類型,如:
public enum Status
? ? {
? ? ? ? Servo_OK = 0,
? ? ? ? Servo_TimeOut,
? ? ? ? Servo_ParErr,
? ? ? ? Servo_LibInitErr,
? ? ? ? Servo_TemperatureLow,
? ? ? ? Servo_TemperatureHight,
? ? ? ? Servo_VoltageLow,
? ? ? ? Servo_VoltageHight,
? ? ? ? Servo_CurrentOver,
? ? ? ? Servo_TorqueOver,
? ? ? ? Servo_FuseErr,
? ? ? ? Servo_PwmErr,
? ? ? ? Servo_CmdFail,
? ? ? ? Servo_ReciveErr,
? ? };
? ?public struct UbtUartServo
? ? {
? ? ? ? [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
? ? ? ? ?string RxBuf;
? ? ? ? //1.定義回調(diào)函數(shù)指針.
? ? ? ? public pwrite write;
? ? ? ? public pread read;
? ? };
三,C#中如何實(shí)現(xiàn)類似于函數(shù)指針功能 (delegate)委托:
C/C++中的 typedef void (*pwrite)Byte buf, Byte size);
在C#可對應(yīng)為:delegate ?void pwrite(ref Byte buf, Byte size);
如 在 C 中
typedef struct?
{
?? ?uint8_t RxBuf[64];
?? ?void ? (*pwrite)(uint8_t *buf,uint8_t size) ? ? C51;
?? ?uint8_t ? (*pread)(uint8_t *buf,uint8_t size,uint8_t mstimeout) ?C51;
} UbtUartServo;
在C#的實(shí)現(xiàn)為:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
? ? public delegate ?void pwrite(ref Byte buf, Byte size);
? ? [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
? ? public delegate ?Byte pread(ref Byte buf, Byte size, Byte mstimeout);
? ? ?
? ? public struct UbtUartServo
? ? {
? ? ? ? [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
? ? ? ? ?string RxBuf;
? ? ? ? //1.定義回調(diào)函數(shù)指針.
? ? ? ? public pwrite write;
? ? ? ? public pread read;
? ? };
其中上面的,Cdecl說明DLL是C格式!
C++或其它可能要用不同的格式(前三個用的多一些,不過不行可以試度其它):
namespace System.Runtime.InteropServices
{
? ? [Serializable]
? ? [ComVisible(true)]
? ? public enum CallingConvention
? ? {
? ? ? ? Winapi = 1,
? ? ? ? Cdecl = 2,
? ? ? ? StdCall = 3,
? ? ? ? ThisCall = 4,
? ? ? ? FastCall = 5,
? ? }
}
不然有可能會出現(xiàn) 如下錯誤:
The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.?
?
? [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
? ? public delegate ?void pwrite(ref Byte buf, Byte size);
?
四,給個例子:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace CshareServoTest
{
? ? public enum Status
? ? {
? ? ? ? Servo_OK = 0,
? ? ? ? Servo_TimeOut,
? ? ? ? Servo_ParErr,
? ? ? ? Servo_LibInitErr,
? ? ? ? Servo_TemperatureLow,
? ? ? ? Servo_TemperatureHight,
? ? ? ? Servo_VoltageLow,
? ? ? ? Servo_VoltageHight,
? ? ? ? Servo_CurrentOver,
? ? ? ? Servo_TorqueOver,
? ? ? ? Servo_FuseErr,
? ? ? ? Servo_PwmErr,
? ? ? ? Servo_CmdFail,
? ? ? ? Servo_ReciveErr,
? ? };
? ? [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
? ? public delegate ?void pwrite(ref Byte buf, Byte size);
? ? [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
? ? public delegate ?Byte pread(ref Byte buf, Byte size, Byte mstimeout);
? ? ?
? ? public struct UbtUartServo
? ? {
? ? ? ? [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
? ? ? ? ?string RxBuf;
? ? ? ? //1.定義回調(diào)函數(shù)指針.
? ? ? ? public pwrite write;
? ? ? ? public pread read;
? ? };
? ? public partial class Form1 : Form
? ? {
? ? ? ? [DllImport("ServoLibDll")]
? ? ? ? static extern void UbtServoGroupInit(ref UbtUartServo Sgroup, pwrite write, pread read);
? ? ? ? [DllImport("ServoLibDll")]
? ? ? ? static extern Status UbtServoMove(ref UbtUartServo Sgroup, Byte ServoID, Byte TargetAngle, Int16 RunTime, UInt16 KeepTime, Byte BackTimeOut);
? ? ? ? public UbtUartServo Test;
? ? ? ? public Form1()
? ? ? ? {
? ? ? ? ? ? InitializeComponent();
? ? ? ? ? ? Test = new UbtUartServo();
? ? ? ? ? ? //Test.write = new pwrite(write);
? ? ? ? ? ? //Test.read = new pread(read);
? ? ? ? ? ? UbtServoGroupInit(ref Test, new pwrite(this.write), new pread(this.read));
? ? ? ? }
? ? ? ? private void TestButton_Click(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? UbtServoMove(ref Test, 0, 120, 25, 500, 50);
? ? ? ? }
? ? ? ? public void write(ref Byte buf, Byte size)
? ? ? ? {
? ? ? ? ? ? ServoTest.Text = "write";
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? public Byte read(ref Byte buf, Byte size, Byte mstimeout)
? ? ? ? {
? ? ? ? ? ? ServoTest.Text = "read";
? ? ? ? ? ? return 1;
? ? ? ? }
? ? }
}
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的C#调用C/C++ DLL的相关说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在WINDOW 系统下如何用批处理命令生
- 下一篇: C# 指针的使用 ref byte 转