用C#编译C++原代码

花开花折 2013-10-05 08:31:16
现自己在做一项目,要用到PLC串口通信,老板要求按照他的原代码来写串口通信部分。(给有原代码,但是用C++写的)现开始用C#来编译原C++代码,遇到一个问题,现求教。谢谢。
A:
因C++原代码中大量用到指针,所以我编译时想用C#中指针,但遇到这个问题?如下:
C++原代码:
BOOL  CDGX::WriteBfm( int nUnit, int addr, int nDevCnt, LPBYTE data )
{
BYTE buf[530];//最大524
LPBYTE p = &buf[4];
int i, n, byt;

while( nDevCnt > 0 )
{
if( m_nUartStopFlag != 0 )
return FALSE;

if( nDevCnt > 127 )
n = 127;
else
n = nDevCnt;

p[0] = 0xf1;
p[1] = ((nUnit<<4)&0xf0) | ((addr>>12)&0xf);

p[2] = (addr>>4)&0xff;
p[3] = (addr<<4)&0xf0;
p = &p[3];

byt = n*2;//字节数
*p++ |= (byt>>4 ) & 0xf;
*p = (byt<<4) & 0xf0;
//数据
for( i=0; i<byt; i++ )
{
int Q = *data++;
*p++ |= (Q>>4 ) & 0xf;
*p = (Q<<4) & 0xf0;
}

for( i = 0; i < MAX_UART_TRY; i++ )
{
SendReq( buf, n*4 + 9 );
if( WriteDevice_Ack() )
break;
if( m_nUartStopFlag != 0 )
return FALSE;
ReShakeHandle(1);
}
if( i == MAX_UART_TRY )
return FALSE;
nDevCnt -= n;
addr += byt;
data += byt;
}
return TRUE;

}

其中:typedef BYTE far *LPBYTE;
typedef unsigned char BYTE;
C#代码(自己编译的):
  public unsafe bool WriteBfm(int nUnit, int addr, int nDevCnt, byte* data)
{

byte[] buf = new byte[530];
fixed (byte* pbuf = buf)
{
fixed (byte* p = &buf[4])
{
int i, n, byt;
while (nDevCnt > 0)
{
if (m_nUartStopFlag != 0)
return false;

if (nDevCnt > 127)
n = 127;
else
n = nDevCnt;

p[0] = 0xf1;
p[1] = (byte)(((nUnit << 4) & 0xf0) | ((addr >> 12) & 0xf));

p[2] = (byte)((addr >> 4) & 0xff);
p[3] = (byte)((addr << 4) & 0xf0);

p = &p[3];

byt = n * 2;//字节数
*p++ |= (byte)((byt >> 4) & 0xf);
*p = (byte)((byt << 4) & 0xf0);
//数据
for (i = 0; i < byt; i++)
{
int Q = *data++;
*p++ |= (byte)((Q >> 4) & 0xf);
*p = (byte)((Q << 4) & 0xf0);
}

for (i = 0; i < MAX_UART_TRY; i++)
{
SendReq(pbuf, n * 4 + 9);
if (WriteDevice_Ack())
break;
if (m_nUartStopFlag != 0)
return false;
ReShakeHandle(1);
}
if (i == MAX_UART_TRY)
return false;
nDevCnt -= n;
addr += byt;
data += byt;
}
return true;

}

}
}

调试时报错:错误:“p”是一个“固定变量”,无法为它赋值
我想可能是我这行代码的原因: fixed (byte* p = &buf[4]) 不知该怎样修改,求教,谢谢。

B:
原代码大概有1500行左右,感觉这样编译太慢,而且工作量比较大(主要是我对C++不熟),不知大家有没有好的点的方法推荐下。谢谢。

C:
听人说,可以把原码封装成类,然后再在C#中调用,但要考虑方法(函数)的参数类型转换问题。我不知这个具体是怎样实现的,是否跟我现在这样完全用C#编译原码??????想了解下具体的实现过程中。谢谢。


...全文
1027 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
wwwspider001 2013-10-08
  • 打赏
  • 举报
回复
你还没明白大家给你说的 解决办法: 1、弄明白你要这个类库干什么用,你打算怎么用 2、提一个接口出来(标准C接口,或者Managed C++接口) 3、根据上面的接口,进行封装,有两种路子:标准C接口的dll通过DllImport调用或者做成Managed C++的.net类库引用后直接使用 注意:你说的替换Open,ReadFile,WriteFile,完全没有必要, 把这些都一起打包,你只需要搞清楚,你怎么用这个库, 不要动里面的内容,否则就没有你老板说的,代码经过考验,很稳定可靠这些的优势了
花开花折 2013-10-08
  • 打赏
  • 举报
回复
啊,现在已能够生成DLL,也能在项目添加DLL引用,但在运行时提示找不到不函数的入口,用VS2008自带的命令工具 dumpbin -exports 查看发现没有找到我封装的函数(也就是我要调用的函数) 以下是DGX.h头文件中内容 DGX.cpp中内容就是实现这些函数,太多就不粘了,
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DGX_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DGX_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#include "define.h"
#include "Serial.h"
#ifdef DGX_EXPORTS
#define DGX_API extern "C" __declspec(dllexport)
#else
#define DGX_API extern "C" __declspec(dllimport)
#endif



// CSerial.h

#ifndef __DGX_FX_PORT_H__
#define __DGX_FX_PORT_H__
#define	MAX_UART_TRY	3


/*
#define	DEVBUF_D	0X4000	//D0000-D7999
#define	DEVBUF_D8	0X8000	//D8000-D8511

#define	DEVBUF_M	0X8800	//M0-M7679(1)
#define	DEVBUF_Y	0X8BC0	//Y0-Y377(1)
#define	DEVBUF_M8	0X8C00
#define	DEVBUF_CX	0X8C40	//C0-C255(触点)
#define	DEVBUF_TX	0X8C60	//T0-T511(触点)

#define	DEVBUF_X	0x8CA0	//X0-X377		256
#define	DEVBUF_S	0X8CE0	//8CE0-8EE0	S0-S4095		768


#define	BDEV_S		0
#define	BDEV_X		1
#define	BDEV_Y		2
#define	BDEV_TX		3
#define	BDEV_M		4
#define	BDEV_CX		5
#define	BDEV_M8		6
#define	BDEV_Db		7

#define	BDEV_KnS	8
#define	BDEV_KnX	9
#define	BDEV_KnY	10
#define	BDEV_KnM	12
#define	BDEV_KnM8	14

#define	WDEV_D		16
#define	WDEV_D8		17
#define	WDEV_R		18
#define	WDEV_TV		19
#define	WDEV_CV1	20
#define	WDEV_CV2	21
#define	WDEV_UG		22
#define	WDEV_KH		23

#define	DEV_ERR		24

*/




#endif
class CDGX
{

public:
	CDGX();
	~CDGX();

	CSerial	*pPort;

	int m_nUartStopFlag;
	int m_nPort, m_nBaud;
	int m_nSend, m_nRecv, m_nError;

	BOOL Open(int port, int baud );
public:

	BOOL ShakeHandle();

	BOOL SetBitDevice( LPSTR strDev, int data );
	BOOL SetBitDevice( UINT addr, int data );

	BOOL ReadDevice( LPSTR strDev, int nDevCnt, LPBYTE data  );
	BOOL ReadDevice( UINT addr, int nDevCnt, LPBYTE data  );
	int ReShakeHandle(int mode = 1);
	int  ReceData( BYTE *buffer, int limit );
	void SendReq( LPBYTE SendBuf, int nSendLength );

	BOOL WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data );
	BOOL WriteDevice( UINT addr, int nDevCnt, LPBYTE data );
	BOOL WriteDevice_Ack();
	BOOL SetBaud( int nBaud );

	int FX_GetDevAddr(LPSTR strDev, XDEV *pDev);
//----------------------------------------------------------------
	BOOL  ReadBfm( int nUnit, int addr, int nDevCnt, LPBYTE data );
	BOOL  WriteBfm( int nUnit, int addr, int nDevCnt, LPBYTE data );
	//BOOL  WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data );
};


DGX_API BOOL _stdcall WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data );  (这个就是我要调用的函数)
注:我感觉还是我的头文件那里有点问题,请各位帮忙看看。非常感谢。
花开花折 2013-10-08
  • 打赏
  • 举报
回复
引用 32 楼 lfqsy 的回复:
用c#的写法去整c++很悲催,这个COM DLL网上应该有很多的,c#的这个类网上也有,
悲催也得做啊,而且正在悲催中
lfqsy 2013-10-08
  • 打赏
  • 举报
回复
用c#的写法去整c++很悲催,这个COM DLL网上应该有很多的,c#的这个类网上也有,
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 17 楼 bigbaldy 的回复:
回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
收到,明天再请教,现在就不麻烦你了。谢谢。晚安,做个好梦。
bigbaldy 2013-10-07
  • 打赏
  • 举报
回复
回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
花开花折 2013-10-07
  • 打赏
  • 举报
回复
这是个什么情况啊,高手都去那呢?
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 19 楼 wwwspider001 的回复:
你老板应该用你一个月的工资把这个工作外包一下更划算~~
应该不用这么久吧,如果对C++熟点,应该很快,我现在整的差不多了,但想改为调用DLL,现在正在做DLL
wwwspider001 2013-10-07
  • 打赏
  • 举报
回复
你老板应该用你一个月的工资把这个工作外包一下更划算~~
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 18 楼 u010909114 的回复:
[quote=引用 17 楼 bigbaldy 的回复:] 回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
收到,明天再请教,现在就不麻烦你了。谢谢。晚安,做个好梦。[/quote]
引用 18 楼 u010909114 的回复:
[quote=引用 17 楼 bigbaldy 的回复:] 回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
收到,明天再请教,现在就不麻烦你了。谢谢。晚安,做个好梦。[/quote] 现在正在尝试这种做法: A:将原码C++中的全部粘到要创建DLL文件中来,即.CPP文件中,然后将原码C++中的DGX.h头文件也粘到创建DLL文件中来,代码如下,不会再报那个错误 5 error C3861: “FX_GetDevAddr”: 找不到标识符(当然新代码里要添加几个头文件)。 B:还是有几个报错的地方正在处理,想知道下我这样做的方法是否正确,因为我尝试过在VS2008中单独写一方法,然后生成一DLL,再然后调用,两者之间差别有点大,有点不确定我这种做法。 C:再次感谢。 这个是DGX.h头文件里的。
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DGX_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DGX_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DGX_EXPORTS
#define DGX_API extern "C" __declspec(dllexport)
#else
#define DGX_APIextern "C" __declspec(dllimport)
#endif


// CSerial.h

#ifndef __DGX_FX_PORT_H__
#define __DGX_FX_PORT_H__


#include "define.h"
#include "Serial.h"
/*
#define	DEVBUF_D	0X4000	//D0000-D7999
#define	DEVBUF_D8	0X8000	//D8000-D8511

#define	DEVBUF_M	0X8800	//M0-M7679(1)
#define	DEVBUF_Y	0X8BC0	//Y0-Y377(1)
#define	DEVBUF_M8	0X8C00
#define	DEVBUF_CX	0X8C40	//C0-C255(触点)
#define	DEVBUF_TX	0X8C60	//T0-T511(触点)

#define	DEVBUF_X	0x8CA0	//X0-X377		256
#define	DEVBUF_S	0X8CE0	//8CE0-8EE0	S0-S4095		768


#define	BDEV_S		0
#define	BDEV_X		1
#define	BDEV_Y		2
#define	BDEV_TX		3
#define	BDEV_M		4
#define	BDEV_CX		5
#define	BDEV_M8		6
#define	BDEV_Db		7

#define	BDEV_KnS	8
#define	BDEV_KnX	9
#define	BDEV_KnY	10
#define	BDEV_KnM	12
#define	BDEV_KnM8	14

#define	WDEV_D		16
#define	WDEV_D8		17
#define	WDEV_R		18
#define	WDEV_TV		19
#define	WDEV_CV1	20
#define	WDEV_CV2	21
#define	WDEV_UG		22
#define	WDEV_KH		23

#define	DEV_ERR		24

*/
#define	MAX_UART_TRY	3

class CDGX
{
public:
	CDGX();
	~CDGX();

	CSerial	*pPort;

	int m_nUartStopFlag;
	int m_nPort, m_nBaud;
	int m_nSend, m_nRecv, m_nError;

	BOOL Open(int port, int baud );
public:

	BOOL ShakeHandle();

	BOOL SetBitDevice( LPSTR strDev, int data );
	BOOL SetBitDevice( UINT addr, int data );

	BOOL ReadDevice( LPSTR strDev, int nDevCnt, LPBYTE data  );
	BOOL ReadDevice( UINT addr, int nDevCnt, LPBYTE data  );
	int ReShakeHandle(int mode = 1);
	int  ReceData( BYTE *buffer, int limit );
	void SendReq( LPBYTE SendBuf, int nSendLength );

	BOOL WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data );
	BOOL WriteDevice( UINT addr, int nDevCnt, LPBYTE data );
	BOOL WriteDevice_Ack();
	BOOL SetBaud( int nBaud );

	int FX_GetDevAddr(LPSTR strDev, XDEV *pDev);
//----------------------------------------------------------------
	BOOL  ReadBfm( int nUnit, int addr, int nDevCnt, LPBYTE data );
	BOOL  WriteBfm( int nUnit, int addr, int nDevCnt, LPBYTE data );
};

#endif


DGX_API BOOL WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data )
这个是DGX.cpp文件中的。
// DGX.cpp : 定义 DLL 应用程序的导出函数。
//

// CIoport.cpp

#include "stdafx.h"
#include "DGX.h"
#include "stdlib.h"

//extern UINT  m_nUartStopFlag
;
//
//外部其它程序传送的终止标志, 不等于0时,终止任何串口传送.

CDGX::CDGX()
{
	m_nSend = m_nRecv = m_nError = 0;
	pPort = NULL;
}

CDGX::~CDGX()
{
	if( pPort != NULL )
	{
		pPort->Close();
		delete pPort;
		pPort = NULL;
	}
}
//============================================================================
BOOL CDGX::WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data )
{
	XDEV pDev;
	UINT addr;

	if( FX_GetDevAddr( strDev, &pDev ) == 0 )
		return FALSE;
	switch(pDev.Name)
	{
	case BDEV_M:	addr = DEVBUF_M  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_M8:	addr = DEVBUF_M8 + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_S:	addr = DEVBUF_S  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_X:	addr = DEVBUF_X  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_Y:	addr = DEVBUF_Y  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case WDEV_D:	addr = DEVBUF_D  + pDev.Number * 2;	break;
	case WDEV_D8:	addr = DEVBUF_D8 + pDev.Number * 2;	break;
	case WDEV_R:	addr = 0x60000 + pDev.Number * 2;	break;
	default:
		return FALSE;
	}
	return WriteDevice( addr, nDevCnt, data );
}

BOOL CDGX::WriteDevice( UINT addr, int nDevCnt, LPBYTE data )
{
	BYTE buf[530];//最大524
	LPBYTE p = &buf[4];
	int i, n, byt;

	while( nDevCnt > 0 )
	{
		if( m_nUartStopFlag != 0 )
			return FALSE;//强制终止, 返回0
		//约束最大发送的数据点数
		if( nDevCnt > 127 )
			n = 127;
		else
			n = nDevCnt;
		//生成代发送数据
		p[0] = 0xe1;
		p[1] = ((addr>>12)&0x0f);
		if( (addr>>16) != 0 )
			p[1] |= 0x60;
		p[2] = (addr>>4)&0xff;
		p[3] = (addr<<4)&0xf0;
		p = &p[3];

		byt = n*2;//字节数
		*p++ |= (byt>>4 ) & 0xf;
		*p =  (byt<<4) & 0xf0;

		for( i=0; i<byt; i++ )
		{
			int Q = *data++;
			*p++ |= (Q>>4 ) & 0xf;
			*p = (Q<<4) & 0xf0;
		}
		//发送
		for( i = 0; i < MAX_UART_TRY; i++ )
		{
			SendReq( buf, n*4 + 9 );
			if( WriteDevice_Ack() )
				break;
			if( m_nUartStopFlag != 0 )
				return FALSE;//强制终止, 返回0
			ReShakeHandle(1);
		}
		if( i == MAX_UART_TRY )
			return FALSE;
		nDevCnt -= n;
		addr += byt;
		data += byt;
	}
	return TRUE;
}


BOOL CDGX::WriteDevice_Ack()
{
	BYTE buf[8];
	if( ReceData( buf, 4 ) == 4 )
		return ( *(UINT*)&buf[0] == 0x013302cc );
	return FALSE;
}


BOOL CDGX::ReadDevice( LPSTR strDev, int nDevCnt, LPBYTE data  )
{
	XDEV pDev;
	UINT addr;

	if( FX_GetDevAddr( strDev, &pDev ) == 0 )
		return FALSE;
	switch(pDev.Name)
	{
	case BDEV_M:	addr = DEVBUF_M  + (pDev.Number/16*2); nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_M8:	addr = DEVBUF_M8 + (pDev.Number/16*2); nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_S:	addr = DEVBUF_S  + (pDev.Number/16*2); nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_X:	addr = DEVBUF_X  + (pDev.Number/16*2); nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_Y:	addr = DEVBUF_Y  + (pDev.Number/16*2); nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;

	case WDEV_D:	addr = DEVBUF_D  + pDev.Number * 2;	break;
	case WDEV_D8:	addr = DEVBUF_D8 + pDev.Number * 2;	break;
	case WDEV_R:	addr = 0x60000 + pDev.Number * 2;	break;
	default:
		return FALSE;
	}
	return ReadDevice( addr, nDevCnt, data  );
}

BOOL  CDGX::WriteBfm( int nUnit, int addr, int nDevCnt, LPBYTE data )
{
	BYTE buf[530];//最大524
	LPBYTE p = &buf[4];
	int i, n, byt;

	while( nDevCnt > 0 )
	{
		if(	m_nUartStopFlag != 0 )
			return FALSE;

		if( nDevCnt > 127 )
			n = 127;
		else
			n = nDevCnt;

		p[0] = 0xf1;
		p[1] = ((nUnit<<4)&0xf0) | ((addr>>12)&0xf);

		p[2] = (addr>>4)&0xff;
		p[3] = (addr<<4)&0xf0;
		p = &p[3];

		byt = n*2;//字节数
		*p++ |= (byt>>4 ) & 0xf;
		*p =  (byt<<4) & 0xf0;
		//数据
		for( i=0; i<byt; i++ )
		{
			int Q = *data++;
			*p++ |= (Q>>4 ) & 0xf;
			*p = (Q<<4) & 0xf0;
		}

		for( i = 0; i < MAX_UART_TRY; i++ )
		{
			SendReq( buf, n*4 + 9 );
			if( WriteDevice_Ack() )
				break;
			if( m_nUartStopFlag != 0 )
				return FALSE;
			ReShakeHandle(1);
		}
		if( i == MAX_UART_TRY )
			return FALSE;
		nDevCnt -= n;
		addr += byt;
		data += byt;
	}
	return TRUE;

}


int CDGX::FX_GetDevAddr(LPSTR strDev, XDEV* pDev)
{
	pDev->Name = DEV_ERR;      //#define	DEV_ERR		24
	char c = strDev[0];
	int nDevNumber;
	strDev++;
	CString str;
	str = strDev;
	nDevNumber = atoi(str);    //功  能: 把字符串转换成长整型数
	if( c == 'M')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_M;
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = BDEV_M8;
			return 1;
		}
	}
	else if( c == 'S')
	{
		if( nDevNumber < 4096 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_S;
			return 1;
		}
	}
	else if( c == 'X')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_X;
			return 1;
		}
	}
	else if( c == 'Y')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_Y;
			return 1;
		}
	}

	else if( c == 'D')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_D;//16
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = WDEV_D8;//17
			return 1;
		}
	}

	else if( c == 'R')
	{
		if( nDevNumber < 32768 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_R;
			return 1;
		}
	}

	return 0;
}


嘿嘿,代码有点多,不好意思呢。谢谢
bigbaldy 2013-10-07
  • 打赏
  • 举报
回复
引用 26 楼 u010909114 的回复:
[quote=引用 18 楼 u010909114 的回复:] [quote=引用 17 楼 bigbaldy 的回复:] 回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
收到,明天再请教,现在就不麻烦你了。谢谢。晚安,做个好梦。[/quote] HELLO,还得麻烦你下下哦。上午研究一上午,有点小小长进,但还是有个槛没迈过去啊,如下: A:还是如上面我所担心的,在函数里面包含函数生成DLL的问题,??? 其中会有一个报错说,错误 5 error C3861: “FX_GetDevAddr”: 找不到标识符
// 12.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "12.h"


BOOL WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data )
{
	XDEV pDev;
	UINT addr;

	if( FX_GetDevAddr( strDev, &pDev ) == 0 )
		return FALSE;
	switch(pDev.Name)
	{
	case BDEV_M:	addr = DEVBUF_M  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_M8:	addr = DEVBUF_M8 + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_S:	addr = DEVBUF_S  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_X:	addr = DEVBUF_X  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_Y:	addr = DEVBUF_Y  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case WDEV_D:	addr = DEVBUF_D  + pDev.Number * 2;	break;
	case WDEV_D8:	addr = DEVBUF_D8 + pDev.Number * 2;	break;
	case WDEV_R:	addr = 0x60000 + pDev.Number * 2;	break;
	default:
		return FALSE;
	}
	return WriteDevice( addr, nDevCnt, data );
}
int CDGX::FX_GetDevAddr(LPSTR strDev, XDEV* pDev)
{
	pDev->Name = DEV_ERR;      //#define	DEV_ERR		24
	char c = strDev[0];
	int nDevNumber;
	strDev++;
	CString str;
	str = strDev;
	nDevNumber = atoi(str);    //功  能: 把字符串转换成长整型数
	if( c == 'M')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_M;
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = BDEV_M8;
			return 1;
		}
	}
	else if( c == 'S')
	{
		if( nDevNumber < 4096 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_S;
			return 1;
		}
	}
	else if( c == 'X')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_X;
			return 1;
		}
	}
	else if( c == 'Y')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_Y;
			return 1;
		}
	}

	else if( c == 'D')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_D;//16
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = WDEV_D8;//17
			return 1;
		}
	}

	else if( c == 'R')
	{
		if( nDevNumber < 32768 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_R;
			return 1;
		}
	}

	return 0;
}

我想可能是我方法那还有问题,不知你上面给我的示例是如何完成的,没有报这个错误。

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
[/quote] 你这个写错了吧,FX_GetDevAddr是类中的静态函数吧,得CDGX::FX_GetDevAddr这样调用
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 18 楼 u010909114 的回复:
[quote=引用 17 楼 bigbaldy 的回复:] 回14楼内容: 1.在C#中你需要调用哪个函数你就导出哪个函数即可,对于你的问题1,你说的没错 2.对于你的问题2,不需要转换成C#呀,你只需要在C#里面调用你用C++写的dll即可,例如你自己的例子: C++中导出

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
C#中引用

[DllImport("ExportedWriteBfm",CallingConvention=CallingConvention.StdCall)]
public unsafe static extern bool ExportedWriteBfm(int nUnit,int addr,int nDevCnt,byte* data);
收到,明天再请教,现在就不麻烦你了。谢谢。晚安,做个好梦。[/quote] HELLO,还得麻烦你下下哦。上午研究一上午,有点小小长进,但还是有个槛没迈过去啊,如下: A:还是如上面我所担心的,在函数里面包含函数生成DLL的问题,??? 其中会有一个报错说,错误 5 error C3861: “FX_GetDevAddr”: 找不到标识符
// 12.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "12.h"


BOOL WriteDevice( LPSTR strDev, int nDevCnt, LPBYTE data )
{
	XDEV pDev;
	UINT addr;

	if( FX_GetDevAddr( strDev, &pDev ) == 0 )
		return FALSE;
	switch(pDev.Name)
	{
	case BDEV_M:	addr = DEVBUF_M  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_M8:	addr = DEVBUF_M8 + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_S:	addr = DEVBUF_S  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_X:	addr = DEVBUF_X  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case BDEV_Y:	addr = DEVBUF_Y  + (pDev.Number/16)*2; nDevCnt = (nDevCnt+(pDev.Number&0xf)+15)/16;	break;
	case WDEV_D:	addr = DEVBUF_D  + pDev.Number * 2;	break;
	case WDEV_D8:	addr = DEVBUF_D8 + pDev.Number * 2;	break;
	case WDEV_R:	addr = 0x60000 + pDev.Number * 2;	break;
	default:
		return FALSE;
	}
	return WriteDevice( addr, nDevCnt, data );
}
int CDGX::FX_GetDevAddr(LPSTR strDev, XDEV* pDev)
{
	pDev->Name = DEV_ERR;      //#define	DEV_ERR		24
	char c = strDev[0];
	int nDevNumber;
	strDev++;
	CString str;
	str = strDev;
	nDevNumber = atoi(str);    //功  能: 把字符串转换成长整型数
	if( c == 'M')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_M;
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = BDEV_M8;
			return 1;
		}
	}
	else if( c == 'S')
	{
		if( nDevNumber < 4096 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = BDEV_S;
			return 1;
		}
	}
	else if( c == 'X')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_X;
			return 1;
		}
	}
	else if( c == 'Y')
	{
		if( nDevNumber <= 377 )
		{
			pDev->Number = (nDevNumber/100)*64;
			nDevNumber = nDevNumber %100;
			pDev->Number += (nDevNumber/10)*8 + (nDevNumber%10);
			pDev->Name = BDEV_Y;
			return 1;
		}
	}

	else if( c == 'D')
	{
		if( nDevNumber < 8000 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_D;//16
			return 1;
		}
		else if( nDevNumber < 8512 )
		{
			pDev->Number = nDevNumber-8000;
			pDev->Name = WDEV_D8;//17
			return 1;
		}
	}

	else if( c == 'R')
	{
		if( nDevNumber < 32768 )
		{
			pDev->Number = nDevNumber;
			pDev->Name = WDEV_R;
			return 1;
		}
	}

	return 0;
}

我想可能是我方法那还有问题,不知你上面给我的示例是如何完成的,没有报这个错误。

EXTERN_C __declspec(dllexport) BOOL WINAPI ExportedWriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data)
{
    return CDGX::WriteBfm(int nUnit,int addr,int nDevCnt,LPBYTE data);
}
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 23 楼 qldsrx 的回复:
你首先要明白那个WriteBfm函数的作用,之后才能考虑如何转换或调用。 初步看下来,函数功能是往外设写入一组数据,写入的是data参数里面的内容,函数内部构造了一个缓存数组buf,最终发送到设备上的是这个buf里面的内容,这个内容的要求是,开始四字节为地址,固定格式: p[0] = 0xf1; p[1] = ((nUnit<<4)&0xf0) | ((addr>>12)&0xf); p[2] = (addr>>4)&0xff; p[3] = (addr<<4)&0xf0; 后面的都是数据部分,整个数据结构就是如此。 下面就考虑如何处理这种收发模式。如果你的外设是通过COM口处理的,那么可以直接用C#的类来收发数据,将数据部分的封装处理用C#来处理,否则就对C++编译为带导出函数的dll,再或者直接新建C++/CLR项目,将原C++代码复制到新项目里。 如果你可以找到外设的最新C#接口,就不用那么麻烦了,现在新出的串口设备,一般都会带有C#的接口而不再给C++的接口了,因为C#的封装会给使用带来巨大的便利,且不会暴露自己的核心代码。
厉害,高手看部分代码就知道我要实现什么功能. A:主要是实现PLC与工业平板电脑之间进行串口通信,通过COM口来进行。 B:原代码是用C++写的,主要是调用这几个函数来实现读取,写入数据的
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
BOOL Open( int nPort, int nBaud, int nDataBits=8  );
	BOOL Close( void );
也就是说,其它的函数都是用来进行数据处理的,为以上函数服务。 D:我现在用VS2008 C#来写的,利用其自带的控件SerialPort,它也有上面类似的四个方法
   public void Write(byte[] buffer, int offset, int count);
  public int Read(byte[] buffer, int offset, int count);
E:现在想利用原代码,将其做成DLL,供在C#中调用,然后用C#中的串口读取数据的方法来替换原代码中C++中读取数据的函数。(主要是想利用原代码中那些辅助数据处理方法,和满足老板的要求。)
花开花折 2013-10-07
  • 打赏
  • 举报
回复
引用 22 楼 dongdongdongJL 的回复:
我觉得你的思路有问题。你应该做的是,使用C#调用c++的dll就可以了。 using System.InteropService static class DllFuncs { [Dllimport("123.dll")] public static extend void Func(); }
THANKS,现在正在朝你说的方向努力啊
qldsrx 2013-10-07
  • 打赏
  • 举报
回复
你首先要明白那个WriteBfm函数的作用,之后才能考虑如何转换或调用。 初步看下来,函数功能是往外设写入一组数据,写入的是data参数里面的内容,函数内部构造了一个缓存数组buf,最终发送到设备上的是这个buf里面的内容,这个内容的要求是,开始四字节为地址,固定格式: p[0] = 0xf1; p[1] = ((nUnit<<4)&0xf0) | ((addr>>12)&0xf); p[2] = (addr>>4)&0xff; p[3] = (addr<<4)&0xf0; 后面的都是数据部分,整个数据结构就是如此。 下面就考虑如何处理这种收发模式。如果你的外设是通过COM口处理的,那么可以直接用C#的类来收发数据,将数据部分的封装处理用C#来处理,否则就对C++编译为带导出函数的dll,再或者直接新建C++/CLR项目,将原C++代码复制到新项目里。 如果你可以找到外设的最新C#接口,就不用那么麻烦了,现在新出的串口设备,一般都会带有C#的接口而不再给C++的接口了,因为C#的封装会给使用带来巨大的便利,且不会暴露自己的核心代码。
dongdongdongJL 2013-10-07
  • 打赏
  • 举报
回复
我觉得你的思路有问题。你应该做的是,使用C#调用c++的dll就可以了。 using System.InteropService static class DllFuncs { [Dllimport("123.dll")] public static extend void Func(); }
wwwspider001 2013-10-07
  • 打赏
  • 举报
回复
是不用这么久,关键是你不熟悉C++,担心你一个月也未必搞得出来,完全通过测试的对应代码 熟悉C++和C#,几个小时之内应该没问题~~
qq465881818 2013-10-06
  • 打赏
  • 举报
回复
花开花折 2013-10-06
  • 打赏
  • 举报
回复
引用 9 楼 bigbaldy 的回复:
你这个不需要用指针写呀,直接操作数组即可。 还有,你可以在C++中导出WriteBfm这个函数,然后用C#调用C++的dll,很容易的
你好,非常感谢你的回帖,我也正打算将C++中的函数导出,然后一个一个做成dll,但现在发现一问题就是原C++中的函数很多都是嵌套调用的,不知你注意到我上面的C++代码没,里面就嵌套调用用了几个函数(上面只是原码中一个函数,还有很多类的)。不知该如何解决,请明示。谢谢。
bigbaldy 2013-10-06
  • 打赏
  • 举报
回复
补充一句:你的错误在于p = &p[3]; 对于你的代码,把

byte[] buf = new byte[530];
改为

byte* pbuf = stackalloc byte[530];
把数组分配到栈里,本身就是固定的,而且性能更好,后面直接byte* p = &buf[4],不用fixed
加载更多回复(13)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧