最近用到研华的一款高精度AD转换卡,PCL816,需要使用C#调用研华库函数中的动态库文件Adsapi32.dll中的函数,参考了网上关于C#调用非托管dll的方法。
其中的难点主要是数据类型的匹配问题。基本的方法在MSDN中关于 c# 调用 C++ 非托管 Dll 的主题有详细的原理说明和例程,我博客上已经转了MSDN这一篇,这里就不赘述了。网上也有很多类型对应关系表,下面是比较好的一个。
C#调用C++编写的Win32 DLL文件时参数对应表
Win32 Types
CLR Type
char, INT8, SBYTE, CHAR
System.SByte
short, short int, INT16, SHORT
System.Int16
int, long, long int, INT32, LONG32, BOOL , INT
INT System.Int32
__int64, INT64, LONGLONG
System.Int64
unsigned char, UINT8, UCHAR , BYTE
System.Byte
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t
System.UInt16
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT
System.UInt32
unsigned __int64, UINT64, DWORDLONG, ULONGLONG
System.UInt64
float, FLOAT
System.Single
double, long double, DOUBLE
System.Double
下面主要说一下调用研华的库函数时遇到的一个新问题。即包含指针类型成员的结构体如何调用的问题。下面是最终成功的源码片段。
/// <summary>
/// 获得输入模拟电压,获取指定句柄设备的输入模拟电压结构体
/// </summary>
/// <param name="DriverHandle">设备句柄</param>
/// <param name="lpAIVoltageIn">输入模拟电压</param>
/// <returns>成功或错误号</returns>
[DllImport("Adsapi32.dll")]
public static extern int DRV_AIVoltageIn(int DriverHandle, ref tagPT_AIVoltageIn lpAIVoltageIn);
/// <summary>
/// 模拟电压结构体
/// </summary>
public struct tagPT_AIVoltageIn
{
public ushort chan; //通道
public ushort gain; //增益码:参考用户手册中的电压范围
public ushort TrigMode; //触发模式:0,内部触发;1,外部触发
public IntPtr voltage; //输入模拟电压的指针
}
在C++函数原型中,tagPT_AIVoltageIn.voltage是一个float* voltage;形式定义的,这里要用C#中特有的指针或句柄类型IntPtr。
调用语句为
dwErrCde = DRV_AIVoltageIn(lDriverHandle, ref ptAIVoltageIn);//读取输入模拟电压
但是这时仍然会提示尝试写入受保护内存。其原因是在调用前没有为