C# 调用C++dll(以基恩士LKG5000为例)

最近有一个基恩士LKG5000测距仪要用,LKG5000可以用RS232和以太网通信,无奈电器用了网线接口,因此只能用以太网通信了。

基恩士提供的以太网通信例程是基于C++的,因此需要用到C#调用C++ DLL的技术。

C#调用C++函数需要按如下格式进行声明:

		[DllImport("LKIF2.dll")]
		public extern static RC LKIF2_CloseDevice();

其中,在调用基恩士C++函数时我碰到了以下几种情况:

1,传入参数和返回值均为基本数据类型,这类函数按照上面的格式直接写,写完调用就可以了,非常简单

		[DllImport("LKIF2.dll")]
		public extern static bool LKIF_ClearFigureData();

2,传入参数和返回值中存在枚举类型,如这里的RC就是基恩士自定义的枚举类型,这时只需要在C#中按照C#的格式将这个枚举类写一遍就可以了

		[DllImport("LKIF2.dll")]
		public extern static RC LKIF2_CloseDevice();
		public enum RC
		{
			RC_OK = 0x0000,             // The operation is completed successfully.
										///
										// Communication error from controller notification
										//
			RC_NAK_COMMAND = 0x1001,    // Command error
			RC_NAK_COMMAND_LENGTH,      // Command length error
			RC_NAK_TIMEOUT,             // Timeout
			RC_NAK_CHECKSUM,            // Check sum error
			RC_NAK_INVALID_STATE,       // Status error
			RC_NAK_OTHER,               // Other error
			RC_NAK_PARAMETER,           // Parameter error
			RC_NAK_OUT_STAGE,           // OUT calculation count limitation error
			RC_NAK_OUT_HEAD_NUM,        // No. of used head/OUT over error
			RC_NAK_OUT_INVALID_CALC,    // OUT which cannot be used for calculation was specified for calculation.
			RC_NAK_OUT_VOID,            // OUT which specified for calculation is not found.
			RC_NAK_INVALID_CYCLE,       // Unavailable sampling cycle
			RC_NAK_CTRL_ERROR,          // Main unit error
			RC_NAK_SRAM_ERROR,          // Setting value error
										///
										// Communication DLL error notification
										//
			RC_ERR_OPEN_DEVICE = 0x2000,// Opening the device failed.
			RC_ERR_NO_DEVICE,           // The device is not open.
			RC_ERR_SEND,                // Command sending error
			RC_ERR_RECEIVE,             // Response receiving error
			RC_ERR_TIMEOUT,             // Timeout
			RC_ERR_NODATA,              // No data
			RC_ERR_NOMEMORY,            // No free memory

			RC_ERR_DISCONNECT,          // Cable disconnection suspected
			RC_ERR_UNKNOWN,             // Undefined error
		}

3,传入参数中带有结构体的,碰到这种实际上我感觉挺麻烦,因为结构体里面一般还会有结构体,并且还有各种关键字如union等。这里以连接函数为例:

EXP RC WINAPI LKIF2_OpenDeviceETHER(LKIF_OPENPARAM_ETHERNET * OpenParam);

这里出现了一个结构体

typedef struct {
	IN_ADDR				IPAddress;
} LKIF_OPENPARAM_ETHERNET;

结构体里面还有一个结构体

//
// IPv4 Internet address
// This is an 'on-wire' format structure.
//
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

可以看到in_addr结构体里面还使用了关键字union,意思是union里面的变量共用了一个地址(重点——),看到这里实际上我也不知道该怎么写了,这么复杂,下面还有一堆define关键字。

看回基恩士给的例程,噢,发现他虽然传入了LKIF_OPENPARAM_ETHERNET,但他只对S_addr进行了赋值,而S_un_b、S_un_w和S_addr又是公用一段地址的,那么我是否只需要在C#的结构体里声明一个ULONG 类型的变量就可以了呢?

	_sprintf_p(strIp,20,"%d.%d.%d.%d\0",_ttoi(strAddr[0]),_ttoi(strAddr[1]),_ttoi(strAddr[2]),_ttoi(strAddr[3]));
	LKIF_OPENPARAM_ETHERNET paramEther;
	paramEther.IPAddress.S_un.S_addr = inet_addr(strIp);
	if(paramEther.IPAddress.S_un.S_addr == INADDR_NONE)
	{
		SHOW_ERROR_MSG;
		return;
	}
	RC rc = LKIF2_OpenDeviceETHER(&paramEther);
	((CLkIF2TestVCDlg*)GetParent())->DisplayCommandResult(_T("LKIF2_OpenDeviceETHER"),rc);

再进一步,既然只有一个变量,那么我是否可以直接将传入的参数更改为long,即如下面所示,因为只写一个long和写一堆结构体和union他们的地址是一样的

		[DllImport("LKIF2.dll")]
		public extern static RC LKIF2_OpenDeviceETHER(ref long IPAddress);

结果表明,这样写确实是可以的。虽然我没有研究过C#调用C++库的具体机制,但我猜想他是按照内存地址来读取和写入变量的,只要地址对的上,那最终结果就没有问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值