最近使用海康的某平台SDK,但是提供的demo没有C#版本,只有C++的,在转换过程中遇到很多问题,简单记录一下.
目录
2.参数为基本类型 + 指针, 例如int*, float*, char*等
由于嵌套指针的使用比较复杂,需要借助一些手段才能够确保正常调用DLL方法
1.参数为基本类型,例如 int,float,char等。
[C++]
void fun(int value);
void fun(float vaue);
void fun(char ch);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(Int32 value);
[DllImport("xxx.dll")]
public static extern void fun(float value);
[DllImport("xxx.dll")]
public static extern void fun(char ch);
2.参数为基本类型 + 指针, 例如int*, float*, char*等
[C++]
void fun(int* value);
void fun(float* vaue);
void fun(char* ch);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(ref Int32 value);
[DllImport("xxx.dll")]
public static extern void fun(ref float value);
参数为char*,在C#中有几种实现方式
A. public static extern void fun(string ch); //ch内容不会改变
B. public static extern void fun(StringBuilder ch); //ch内容会改变
3. 参数为结构体
[C++]
struct point
{
int value; //基本类型
char ch; //基本类型
int number[100]; //数组
char buffer[100]; //字符串数组
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
4. 参数为结构体指针
[C++]
void fun(point* pt);
[C#]
[DllImport("xxx.dll")]
public static extern void fun(ref point pt);
5.参数为结构体, 并且结构体还嵌套结构体
[C++]
struct point
{
int value; //基本类型
char ch; //基本类型
int number[100]; //数组
char buffer[100]; //字符串数组
struct point pt; //嵌套结构体
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public point pt;
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
6. 参数为结构体, 并且结构体还嵌套结构体指针或者双指针
[C++]
struct point
{
int value; //基本类型
char ch; //基本类型
int number[100]; //数组
char buffer[100]; //字符串数组
struct point* p1; //嵌套结构体指针
struct point** p2; //嵌套结构体双指针
};
void fun(point pt);
[C#]
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public IntPtr p1; //使用IntPtr替代嵌套指针
public IntPtr p2; //使用IntPtr替代嵌套指针
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
7.回调函数使用
[c++]
typedef void (__stdcall *pStreamCallback)(long lSession, int iStreamType, const char* data, int dataLen, void* pUser);
HIKPT_EXTERN long HIKPT_API HikPt_StartPreview(const char* szCameraIndexCode, void* hWnd, pStreamCallback pFun, void* pUserData, HIK_STREAM_TYPE nStreamType);
[c#]
public delegate void pStreamCallback(long lSession, int iStreamType, string data, int dataLen, IntPtr pUser);
[DllImport("xxxx.dll", CharSet = CharSet.Ansi, EntryPoint = "DPSDK_Pt_StartPreview", ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
public static extern long Pt_StartPreview(string szIndexCode, IntPtr hWnd, pStreamCallback pFun, IntPtr pUserData, HIK_STREAM_TYPE nStreamType);
由于嵌套指针的使用比较复杂,需要借助一些手段才能够确保正常调用DLL方法
[C#]
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct point
{
public Int32 value;
public char ch;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public Int32[] number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public char[] buffer;
public IntPtr p1; //使用IntPtr替代嵌套指针
public IntPtr p2; //使用IntPtr替代嵌套指针
}
[DllImport("xxx.dll")]
public static extern void fun(point pt);
static void Main(string[] args)
{
point pt = new point();
pt.p1 = Marshal.AllocHGlobal(Marshal.Sizeof(typeof(point)));
pt.p2 = Marshal.AllocHGlobal((Marshal.SizeOf(typeof(point))) * 2);
try
{
pt.value = 1;
//实现给p1赋值
point ptt = new point();
ptt.value = 1;
Marshal.StructureToPtr(ptt, pt.p1, false);
//实现给p2赋值
//由于双指针不能够直接传值,需要用到中间结构的数组指针
IntPtr[] ptr = new IntPtr[2];
ptr[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(point)));
ptr[1] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(point)));
try
{
Marshal.StructureToPtr(ptt, ptr[0], false);
Marshal.Copy(ptr, 0, pt.p2, 2);
fun(pt);
//测试返回的指针值是否正确
ptt = (point)Marshal.PtrToStructure(pt.p1, typeof(point));
Marshal.Copy(pt.p2, ptr, 0, 2);
ptt = (point)Marshal.PtrToStructure(ptr[0], typeof(point));
ptt = (point)Marshal.PtrToStructure(ptr[1], typeof(point));
}
catch(System.Exception e)
{
string str = e.Message;
}
finally
{
Marshal.FreeHGlobal(ptr[0]);
Marshal.FreeHGlobal(ptr[1]);
}
}
catch(System.Exception e)
{
string str = e.Message;
}
finally
{
Marshal.FreeHGlobal(pt.p1);
Marshal.FreeHGlobal(pt.p2);
}
}
}
更详细一些的
C++中的DLL函数原型为
extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsigned char* 变量名2)
extern "C" __declspec(dllexport) bool 方法名二(const unsigned char* 变量名1, char* 变量名2)
C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试
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++:结构体 ---- c#:public struct 结构体{};
c++:结构体 **变量名 ---- c#:out 变量名 //C#中提前申明一个结构体实例化后的变量名
c++:结构体 &变量名 ---- c#:ref 结构体 变量名
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++中一个字符用一个字节表示,C#中一个字符用两个字节表示
c++:char 数组名[数组大小] ---- c#:MarshalAs(UnmanagedType.ByValTStr, SizeConst = 数组大小)] public string 数组名; ushort
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 变量名[数组大小] ---- c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=数组大小)] public string 变量名;
c++:struct 结构体名 *变量名 ---- c#:ref 结构体名 变量名
c++:委托 变量名 ---- c#:委托 变量名
c++:int ---- c#:int
c++:int ---- c#:ref int
c++:int & ---- c#:ref int
c++:int * ---- c#:ref int //C#中调用前需定义int 变量名 = 0;
c++:*int ---- c#:IntPtr
c++:int32 PIPTR * ---- c#:int32[]
c++:float PIPTR * ---- c#:float[]
c++:double** 数组名 ---- c#:ref double 数组名
c++:double*[] 数组名 ---- c#:ref double 数组名
c++:long ---- c#:int
c++:ulong ---- c#:int
c++:UINT8 * ---- c#:ref byte //C#中调用前需定义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
unsigned char对应public byte
文章是抄的,可以用,如果各位大虾在使用过程中发现不对地方,我会优先测试,然后更新。