C# 与 C++ 交互

一、关于非托管C++调用C# DLL的问题:

1.可以在二者之间增加一个桥梁,使用C++/CLI(取代了托管C++) ,原生C++代码为主调程序,C++/CLI和C#/.NET 均为动态库*.dll。

2.原生C++可以使用函数LoadLibrary(dllFileName)加载dll,然后使用函数GetProcAddress()调用C++/CLI里的接口函数

代码片段:

BOOL dealDll(MachineConf2 &dllMachine)
{
	BOOL bolRet = FALSE;
	DLLInfo *dllInfoTmp;
	CString inDllFileName;
	char cTmp[1024];

	LOG4CXX_TRACE(logger_, "dealDll start...");
	inDllFileName = dllMachine.dllFileName;
	if (inDllFileName.GetLength() > 0)
	{
		dllInfoTmp = &(dllStruct.dllInfo[dllStruct.iDllCount]);

		if (!PathFileExists(inDllFileName.GetBuffer()))
		{
			sprintf(cTmp, "dealDll, dllFileName dosn't exist, dllFileName =[%s]", inDllFileName.GetBuffer());
			inDllFileName.ReleaseBuffer();
			LOG4CXX_WARN(logger_, cTmp);

			return bolRet;
		}
		else
		{
			inDllFileName.ReleaseBuffer();
			for(int i = 0; i< dllStruct.iDllCount; i++)
			{
				if (dllStruct.dllInfo[i].dllFilename == inDllFileName)
				{
					dllMachine.dllIndex = i;
					return TRUE;
				}
			}
		}
		
		dllInfoTmp->dllFilename = inDllFileName;

		dllInfoTmp->pHModule = LoadLibrary(inDllFileName);
		if (NULL == dllInfoTmp->pHModule)
		{
			sprintf(cTmp, "dealDll, load dll fail, dllFileName =[%s]", inDllFileName.GetBuffer());
			inDllFileName.ReleaseBuffer();
			LOG4CXX_WARN(logger_, cTmp);

			return bolRet;
		}

		dllInfoTmp->funInital = (FunInital)GetProcAddress(dllInfoTmp->pHModule, "initalMachine");
		if (NULL == dllInfoTmp->funInital)
		{
			sprintf(cTmp, "dealDll, get function initalMachine fail, dllFileName =[%s]", inDllFileName.GetBuffer());
			inDllFileName.ReleaseBuffer();
			LOG4CXX_WARN(logger_, cTmp);

			return bolRet;
		}

		dllInfoTmp->funFree = (FunFree)GetProcAddress(dllInfoTmp->pHModule, "freeMachine");
		if (NULL == dllInfoTmp->funFree)
		{
			sprintf(cTmp, "dealDll, get function freeMachine fail, dllFileName =[%s]", inDllFileName.GetBuffer());
			inDllFileName.ReleaseBuffer();
			LOG4CXX_WARN(logger_, cTmp);

			return bolRet;
		}

		dllInfoTmp->setCallBackfun = (SetCallBackFun)GetProcAddress(dllInfoTmp->pHModule, "SetDataCallBackFun");

		if (NULL == dllInfoTmp->setCallBackfun)
		{
			sprintf(cTmp, "dealDll, get function SetDataCallBackFun fail, dllFileName =[%s]", inDllFileName.GetBuffer());
			inDllFileName.ReleaseBuffer();
			LOG4CXX_WARN(logger_, cTmp);

			return bolRet;
		}
		//ADD set callbackfun
		dllInfoTmp->setCallBackfun(CallbackDataQueue);
		
		dllMachine.dllIndex = dllStruct.iDllCount;

		dllStruct.iDllCount++;
		bolRet = TRUE;
	}
	else
	{
		LOG4CXX_WARN(logger_, "dealDll, input dllFileName is NULL!");
		return bolRet;
	}


	LOG4CXX_TRACE(logger_, "dealDll End...");
	return bolRet;
}

二、关于C++与C#数据交互&C#/.NET与C++/CLI函数互调:

C#调C++

C++

adapter.h

#ifndef O_U_Adapter_H_
#define O_U_Adapter_H_

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <time.h>



//此方式为使用经典C方式生成动态库
#ifdef _EXPORTING 
#define API_DECLSPEC extern "C" _declspec(dllexport) 
#else 
#define API_DECLSPEC  extern "C" _declspec(dllimport) 
#endif


API_DECLSPEC void  DataTransferGate(char* str);
API_DECLSPEC void  AlarmTransferGate(char* str);
API_DECLSPEC char* GetXmlAddress();
API_DECLSPEC char* GetElementNode();
API_DECLSPEC int GetPublishingInterval();
API_DECLSPEC char* GetMachineIP();
API_DECLSPEC int GetPublishingBehaviour();
//测试
API_DECLSPEC int Connect();

#endif//O_U_Adapter_H_

adapter.cpp

void DataTransferGate(char *str)
{
	std::cout << "Data GATE Start " << std::endl;

	string json = str;

	//WriteLog("0.txt", str);

	if (sData.size() < QUEUE_MAXSIZE)
	{
		sData.push(json);
	}
	else
	{
		while (!sData.empty())
			sData.pop();
	}
}


int GetPublishingInterval()
{
	return  atoi((char*)pSTRUCT.machine.collCycle.data());
}
char* GetMachineIP()
{
	return (char*)pSTRUCT.machine.machineIp.data();
}

C#

    public class DllImport
    {
        [DllImport("O.U.Adapter.dll", EntryPoint = "DataTransferGate", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern void DataTransfer([MarshalAs(UnmanagedType.LPStr)]string str);

        [DllImport("O.U.Adapter.dll", EntryPoint = "AlarmTransferGate", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
        public static extern void AlarmTransfer([MarshalAs(UnmanagedType.LPStr)]string str);

        [DllImport("O.U.Adapter.dll", EntryPoint = "GetPublishingInterval")]
        public static extern int GetPublishingInterval();

        [DllImport("O.U.Adapter.dll", EntryPoint = "GetMachineIP")]
        public static extern IntPtr GetMachineIPByBytes();
    }

 

C++调C#

C++

using namespace O::U::Application;
#ifdef _DEBUG
#using "O.U.Application.dll"
#else
#using "O.U.Application.dll"
#endif // _DEBUG
int Connect()
{
	int stopTimeout = -1;//Timeout.Infinite;
	System::String^ endpointURL;
	bool userAuth = false;

	// TODO: 读取配置文件信息。
	//pSTRUCT.machine.machineIp = "127.0.0.1";
	//pSTRUCT.machine.machinePort = "51210";
	endpointURL = gcnew String(pSTRUCT.machine.machineIp.c_str()) + ":" + gcnew String(pSTRUCT.machine.machinePort.c_str());


	userAuth = (pSTRUCT.machine.userName != "" &&
		pSTRUCT.machine.password != "") ? true : false;//条件成立赋值true,条件不成立赋值false
	System::String^ userName = gcnew String(pSTRUCT.machine.userName.c_str());//"Client";
	System::String^ password = gcnew String(pSTRUCT.machine.password.c_str());//"SUNRISE";

	Log4netWrapper ^logger;
	logger->Instance->InfoFormat("userName:{0},password:{1}", userName, password);

	OUClient ^client;

	if (userAuth)
	{
		client = gcnew Client(endpointURL, stopTimeout, userName, password);
	}
	else
	{
		client = gcnew Client(endpointURL, stopTimeout);
	}

	client->Run();

	return (int)Client::ExitCode;
}

 

基本数据类型转换:

三、关于回调

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 

#include <stdio.h>
typedef int(*callback)(int,int);

int add(int a,int b,callback p){
    //特定的事件或条件发生时,调用者使用函数指针调用回调函数
    return (*p)(a,b);
}

int add(int a,int b){
    return a+b;
}
int main(int argc,char *args[]){
    //将函数的地址注册给调用者
    int res = add(4,2,add);
    printf("%d\n",res);
    return 0;
}

 

 

参考:

https://blog.csdn.net/wangweitingaabbcc/article/details/7663949

https://blog.csdn.net/yanlinembed/article/details/78920276

https://blog.csdn.net/AGroupOfRuffian/article/details/78530094

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值