博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过CLR API实现C++调用C#代码交互
阅读量:6414 次
发布时间:2019-06-23

本文共 3269 字,大约阅读时间需要 10 分钟。

对于某些跨平台程序,这也就意味着只能在windows下使用了

不过最近.Net开源或许以后可以跨平台

 

之前花了一些时间研究COM方式调用,太繁琐不推荐。

后来尝试使用CLR C++,虽然可以用.Net的接口直接载入,但他只是一层C++的皮,最终没能运用在实际项目中。

最后使用MS提供的CLR API接口,完成调用

 

=======================================================

有几个注意点:

1.官方一直强调的签名格式static int pwzMethodName (String pwzArgument),并非某个C#特性,而是函数格式必须是带一个string参数返回int型。否则在调用时会报找不到方法。

2.ExecuteInDefaultAppDomain中,dll路径支持相对路径格式,"xx.dll"是可以被识别的。

3.GetRuntime方法获得的.Net版本号,需要去c:/windows/Microsoft.NET下找,64位对应Framework64,普通版对应Framework。如果目标机器没有该文件夹,说明对应版本的.net未安装。那么程序就会报错。版本号第三位数字似乎是死的,应该都是统一的发行版。

4.在创建测试项目时,需要点掉预编译头选项,否则会出现许多莫名其妙的错误。

5.需要在管理员权限下使用

6.类可以是静态类或者非静态,但函数必须是静态函数

 

参考代码摘自github:

 

具体上代码

 

C#

using System;using System.Collections.Generic;using System.IO;using System.Text;namespace ClassLibrary1{    public class Class1    {        public static int EntryPoint(string arg)        {            File.AppendAllText("C:/xx.txt", "qweqwe");            return 0;        }    }}
View Code

 

 

C++

//Reference From GitHub entice:https://github.com/entice/client/blob/42f388d68b1954ef244c379560eeb4867ae80b7e/Loader/Loader/DllMain.cpp#include 
#include
#include
#include
#include
#include
#pragma comment(lib, "mscoree.lib")#define BUFFER_SIZE 500#include "stdafx.h"void StartTheDotNetRuntime(LPCWSTR runtimeVersion, LPCWSTR dllPath, LPCWSTR startClass, LPCWSTR startMethod, LPCWSTR startArgument){ ICLRMetaHost *pMetaHost = NULL; ICLRMetaHostPolicy *pMetaHostPolicy = NULL; ICLRDebugging *pCLRDebugging = NULL; CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&pMetaHostPolicy); CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&pCLRDebugging); DWORD dwVersion = 0; DWORD dwImageVersion = 0; ICLRRuntimeInfo *pRuntimeInfo; HRESULT result; result = pMetaHost->GetRuntime(runtimeVersion, IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo); assert(SUCCEEDED(result)); ICLRRuntimeHost * pRuntimeHost = NULL; result = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pRuntimeHost); assert(SUCCEEDED(result)); result = pRuntimeHost->Start(); assert(SUCCEEDED(result)); DWORD dwRetCode = 0; result = pRuntimeHost->ExecuteInDefaultAppDomain(dllPath, startClass, startMethod, startArgument, &dwRetCode); assert(SUCCEEDED(result)); pRuntimeHost->Stop(); pRuntimeHost->Release(); pRuntimeInfo->Release(); pCLRDebugging->Release(); pMetaHostPolicy->Release(); pMetaHost->Release();}void Loader(){ wchar_t* runtimeVersionSpace = new wchar_t[BUFFER_SIZE]; wchar_t* dllPathSpace = new wchar_t[BUFFER_SIZE]; wchar_t* currentDir = new wchar_t[BUFFER_SIZE]; GetCurrentDirectoryW(BUFFER_SIZE, currentDir); StartTheDotNetRuntime(L"v4.0.30319", L"ClassLibrary1.dll", L"ClassLibrary1.Class1", L"EntryPoint", L""); free(runtimeVersionSpace); free(dllPathSpace); free(currentDir);}int _tmain(int argc, _TCHAR* argv[]){ HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Loader, NULL, 0, NULL); for (size_t i = 0; i < 10; i++) { Sleep(100); } TerminateThread(handle, 0); return 0;}
View Code

 

 

然后把c#生成的dll,放到c++的build目录下,再以管理员权限执行即可。

最后会在c盘根目录下创建一个xx.txt文件。说明调用C#成功

转载地址:http://blzra.baihongyu.com/

你可能感兴趣的文章
如何设定VDP同时备份的任务数?
查看>>
ipsec的***在企业网中的经典应用
查看>>
过来人谈《去360还是留在百度?》
查看>>
mysql备份工具innobackupex,xtrabackup-2.1安装,参数详解
查看>>
【复制】slave筛选复制之二(create/drop table语句)
查看>>
Movie Store OpenCart 自适应主题模板 ABC-0249
查看>>
RedHat linux YUM本地制作源
查看>>
apache端口占用问题
查看>>
本地Office Project计划表同步到SharePoint2013任务列表的权限问题
查看>>
Windows2008 R2 GAC权限问题
查看>>
洛谷——P1469 找筷子
查看>>
几句话就能让你明白:网络地址转换(NAT)
查看>>
springboot项目自定义注解实现的多数据源切换
查看>>
特此说明
查看>>
使用flume替代原有的scribe服务
查看>>
用脚本来定制ESXI安装镜像
查看>>
微软企业级加解密解决方案MBAM架构
查看>>
没有苦劳,只有功劳!
查看>>
基于ThinkPHP写的一个简单的CMS系统
查看>>
Exchange 2010 DAG local and Site DR/Failover and Fail back
查看>>