C# 访问C++的Dll的实现

来源:互联网 发布:百度云盘 for mac 编辑:程序博客网 时间:2024/05/18 01:34

在我们开放过程中,常常会遇到c++的dll,我们可以使用回调方法去访问,如果别人给的dll是导出的类,而且是虚类的方法传出信息,那么我们就可以从c++转成CLR的dll,然后转到C# 中。原理我就不说了,直接上代码吧!通过头文件,大家直接实现去!很方便哟!可是花了我好长时间才全部实现的。呵呵!

具体请看: c++的dll如下:

//=============================================================================
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SHZDTRADELIB_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// SHZDTRADELIB_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
// 向少中 2013-06-07
//=============================================================================
#ifdef SHZDTRADELIB_EXPORTS
#define SHZDTRADELIB_API __declspec(dllexport)
#else
#define SHZDTRADELIB_API __declspec(dllimport)
#endif

#ifdef __cplusplus
//===================================================================================
// 对外导出的接口,先绑定,然后初始化,绑定的端口如果为0,表示只做客户端通信
// 如果不为0表示做服务器端,同时做客户端。
//===================================================================================
class IShZdTradeLibIn
{  
public:
    virtual void Release() = 0; 
 virtual int InitShZdServer()=0;//初始化服务器
 virtual int RegisterFront(const char *pszFrontAddress,int portNum,const char* localAdress,int localPortNum)=0; //连接前置服务器
 virtual int SendTradeInfo(int clientId,const char* tradeInfo)=0;//向交易服务器发送交易请求 

 virtual int BindListenIpPort(const char* lIpAdress,int port)=0; //绑定监听的Ip地址和端口
 virtual int SendOneClientTradeInfo(int clientId,const char* tradeInfo)=0;//向一个客户端发送信息
 virtual int SendAllClientTradeInfo(const char* tradeInfo)=0;//向所有客户端发送信息
 virtual int LibStart()=0; //开始
};
//====================================================================================
// 导入到DLl内部的接口
//====================================================================================
class IShZdTradeLibOut
{
public: 
 virtual int OnNotifyLoggerInfo(const char* logInfo)=0; //记录logInfo
 virtual int OnNotifyDisconnectedClient(int clientId,const char * errorInfo)=0;//客户端断开连接的返回信息
 virtual int OnNotifyNewConnectionClient(int clientId)=0; //新的客户端连接进来
 virtual int OnNotifyTradeInfo(int clientId,const char* tradeInfo)=0;//接收到客户端传来的信息
};
// 此类是从 ShZdTradeLib.dll 导出的
class SHZDTRADELIB_API CShZdTradeLib {
public:
};
//导出接口的实例
typedef IShZdTradeLibIn* ShZdTradeLibInHandle;
typedef IShZdTradeLibOut* ShZdTradeLibOutHandle;
#else 

#endif

#ifdef __cplusplus
#   define EXTERN_C     extern "C"
#else
#   define EXTERN_C
#endif

//===============================================
// 工厂方法建立ShZdTradeLibIn的实例
//================================================
EXTERN_C SHZDTRADELIB_API ShZdTradeLibInHandle
GetShZdTradeLib(void);
//================================================
// 向dll内部设置接口实例,外面实现这个实例
//================================================
EXTERN_C SHZDTRADELIB_API void
SetShZdMarketLib(ShZdTradeLibOutHandle OutHandle);

那么我们就可以这样写CLR的DLL,以方便C#使用:

#pragma once
using namespace System;
//using namespace std;
#include "../ShZdTradeLib/ShZdTradeLib/ShZdTradeLib.h"
//向CShap中传递信息的导出函数
#ifndef ShZdTradeCRLLib_H
#define ShZdTradeCRLLib_H

typedef void (__stdcall * Callback)(const char* text);
extern "C" __declspec(dllexport)
 extern void __stdcall SetGlobalCallback(Callback handler);

typedef void (__stdcall * CallbackClient)(int client_id,const char* text);
extern "C" __declspec(dllexport)
 extern void __stdcall SetGlobalCallbackClient(CallbackClient handler);

typedef void (__stdcall * CallbackNewConnection)(int client_id);
extern "C" __declspec(dllexport)
 extern void __stdcall SetGlobalCallbackNewConnection(CallbackNewConnection handler);
#endif

Callback Handler = 0;
void __stdcall SetGlobalCallback(Callback handler)
{
 Handler = handler;
};

CallbackClient ClientHandler=0;
void __stdcall SetGlobalCallbackClient(CallbackClient handler)
{
 ClientHandler=handler;
};

CallbackNewConnection ClientNewHandler=0;
void __stdcall SetGlobalCallbackNewConnection(CallbackNewConnection handler)
{
 ClientNewHandler=handler;
}

//===========================================================
// 接收c的dll的信息,并通过导出函数,向CShap传递信息
//===========================================================
public class ShZdTradeCRLLibOut:public IShZdTradeLibOut
{
public:  
 int OnNotifyTradeInfo(const char* tradeInfo); //接收交易的返回信息
 
 int OnNotifyLoggerInfo(const char* logInfo); //记录logInfo
 int OnNotifyDisconnectedClient(int clientId,const char * errorInfo);//客户端断开连接的返回信息

 int OnNotifyNewConnectionClient(int clientId); //新的客户端连接进来
 int OnNotifyTradeInfo(int clientId,const char* tradeInfo);//接收到客户端传来的信息

};

//===============================================================
// 向dell中写信息的对象
//===============================================================
public ref class ShZdTradeCRLLibIn
{  
 private:
  IShZdTradeLibIn* myLibIn;  
 public :
  /*
  * 建立方法
  */
  ShZdTradeCRLLibIn()
  {  
   myLibIn=::GetShZdTradeLib();
   
   ::SetShZdMarketLib(new ShZdTradeCRLLibOut);
  }
  /*
  * 析构方法
  */
  ~ShZdTradeCRLLibIn()
  {
   myLibIn->Release();   
  }

  int CRLInitShZdServer()//初始化服务器
  {
   return myLibIn->InitShZdServer();
  }
  
  int CRLRegisterFront(const char* pszFrontAddress,int portNum,
   const char* localAdress,int localPortNum)//连接前置服务器
  {
   return myLibIn->RegisterFront(pszFrontAddress,portNum,localAdress,localPortNum);   
  }
  
  int CRLSendTradeInfo(int clientId,const char* tradeInfo)//向交易服务器发送交易请求 
  {
   return myLibIn->SendTradeInfo(clientId,tradeInfo);
  }

  int CRLBindListenIpPort(const char* lIpAdress,int port) //绑定监听的Ip地址和端口
  {
   return myLibIn->BindListenIpPort(lIpAdress,port);
  }

  int CRLSendOneClientTradeInfo(int clientId,const char* tradeInfo)//向一个客户端发送信息
  {
   return myLibIn->SendOneClientTradeInfo(clientId,tradeInfo);
  }

  int CRLSendAllClientTradeInfo(const char* tradeInfo)//向所有客户端发送信息
  {
   return  myLibIn->SendAllClientTradeInfo(tradeInfo);
  }

  int CRLLibStart() //开始  
  {
   return myLibIn->LibStart();
  }
};

CLR的DLL实现了,那么就可以写C#的Dll了,这样在工程中使用就非常方便:

C#的代码:

public class CSharpShZdTradeLibOut
    {
        //返回字符串的回调
        [DllImport("ShZdTradeCRLLib.dll", EntryPoint = "SetGlobalCallback",
            CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern void SetGlobalCallback(Callback cb);

        private delegate void Callback(string text);
        private Callback CallbackInstance;
        //返回int ,string的回调
        [DllImport("ShZdTradeCRLLib.dll", EntryPoint = "SetGlobalCallbackClient",
            CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern void SetGlobalCallbackClient(CallbackClient cb);

        private delegate void CallbackClient(int clientId, string text);
        private CallbackClient CallbackClientInstance;
        //返回Int的回调
        [DllImport("ShZdTradeCRLLib.dll", EntryPoint = "SetGlobalCallbackClient",
            CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern void SetGlobalCallbackNewConnection(CallbackNewConnection cb);

        private delegate void CallbackNewConnection(int clientId);
        private CallbackNewConnection CallbackNewConnectionInstance;
        /// <summary>
        /// 定义运行返回信息事件
        /// </summary>
        public event DllInfoEvent.DllInfoHandler InfoLogHandler;
        /// <summary>
        /// 定义接收信息的事件
        /// </summary>
        public event DllInfoEvent.DllInfoHandler InfoRecHandler;
        /// <summary>
        /// 定义新客户连接事件
        /// </summary>
        public event DllInfoEvent.DllInfoHandler ClientNewHandler;

        public CSharpShZdTradeLibOut()
        {
            //运行log返回的回调
            CallbackInstance = new Callback(Handler_GlobalCallback);
            SetGlobalCallback(CallbackInstance);
            //客户信息返回的回调、客户断开信息的返回
            CallbackClientInstance = new CallbackClient(Handler_ClientInfoBack);
            SetGlobalCallbackClient(CallbackClientInstance);
            //服务器接受到客户连接的返回
            CallbackNewConnectionInstance = new CallbackNewConnection(Handler_NewClientConnection);
            SetGlobalCallbackNewConnection(CallbackNewConnectionInstance);
        }

C#工程中就这样使用了:

public partial class Form1 : Form
    {       
        public Form1()
        {
            InitializeComponent();
        }

        private CSharpShZdTradeLibIn myLibIn;

        private CSharpShZdTradeLibOut myLibOut;

        private void button1_Click(object sender, EventArgs e)
        {
            myLibIn = new CSharpShZdTradeLibIn();

            myLibOut = new CSharpShZdTradeLibOut();
            myLibOut.InfoLogHandler += new DllInfoEvent.DllInfoHandler(getDllInfo);
            myLibOut.InfoRecHandler += new DllInfoEvent.DllInfoHandler(getDllInfo);
            myLibOut.ClientNewHandler += new DllInfoEvent.DllInfoHandler(getDllInfo);
            myLibIn.CSharp_InitShZdServer();
            myLibIn.CSharp_BindListenIp("", 0);
            myLibIn.CSharp_LibStart();                    
        }

        public void getDllInfo(object sender, DllInfoEvent e)
        {
            DllInfo info=e.EventArg;
            MessageBox.Show(info.infoContent);
        }       
    }

注意各个工程中的引用,顺序!

大家觉得是不是很方便呀!

原创粉丝点击