通过CLR API实现C++调用C#代码交互

通过CLR API实现C++调用C#代码交互

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

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

 

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

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

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

 

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

有几个注意点:

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:

https://github.com/entice/client/blob/42f388d68b1954ef244c379560eeb4867ae80b7e/Loader/Loader/DllMain.cpp

 

具体上代码

 

C#

通过CLR API实现C++调用C#代码交互
通过CLR API实现C++调用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++

通过CLR API实现C++调用C#代码交互
通过CLR API实现C++调用C#代码交互

//Reference From GitHub entice:https://github.com/entice/client/blob/42f388d68b1954ef244c379560eeb4867ae80b7e/Loader/Loader/DllMain.cpp

#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <mscoree.h>
#include <metahost.h>
#include <assert.h>

#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#成功

转载于:https://www.cnblogs.com/hont/p/4188964.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109612.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 使用RSS实现自动动漫更新提醒及下载(追番)

    使用RSS实现自动动漫更新提醒及下载(追番)喜欢追动漫番并且喜欢下载下来看和收藏的各位应该都有个觉得不方便的地方,那就是每天都得跑去下载的网站进行查看追的剧是否更新。而这并不是难受的地方,更麻烦的是还要记每部剧上个星期放到了第几集,有时候忘记看了,下个星期跳过了一集下载下来,打开看了才发现,然后还得回去下,这真是gay得一批。。好吧闲话有点多了。进入正题吧。作为程序狗的各位对这种需求自然有自己的解决办法,自己写程序进行定时检查是最直接

    2022年8月23日
    8
  • C++——string字符串类具体用法

    C++——string字符串类具体用法引言:C++ 大大增强了对字符串的支持,除了可以使用C风格的字符串,还可以使用内置的 string 类。string 类处理起字符串来会方便很多,完全可以代替C语言中的字符数组或字符串指针。string 是 C++ 中常用的一个类,它非常重要,我们有必要在此单独讲解一下。定义使用 string 类需要包含头文件,下面的例子介绍了几种定义 string 变量(对象)的方法:#include…

    2022年8月18日
    26
  • win7电脑卡顿严重解决方法_电脑卡顿一下

    win7电脑卡顿严重解决方法_电脑卡顿一下最近有很多游戏玩家和小编说win7电脑玩2D游戏经常发生卡顿,游戏卡顿问题确实让玩家苦恼,因为导致2D游戏经常发生卡顿的原因有很多种,那么win7电脑玩2D游戏经常发生卡顿怎么办?不要着急,针对此问题,下面小编告诉大家造成2D游戏经常发生卡顿的六大解决方法。解决方法一:1、建议下载并安装【百度电脑专家】,2、打开【百度电脑专家】,在搜索框内输入“玩游戏卡”,在搜索结果里面选择第一项的【立即修复】,…

    2025年10月27日
    3
  • hadoop集群老的资源管理Mrv1与Yarn资源管理器的工作流程和对比

    hadoop集群老的资源管理Mrv1与Yarn资源管理器的工作流程和对比hadoop集群老的资源管理Mrv1与Yarn资源管理器的工作流程和对比

    2022年4月23日
    43
  • SpringBoot自动装配原理「建议收藏」

    SpringBoot自动装配原理「建议收藏」SpringBoot项目无需各种配置文件,一个main方法,就能把项目启动起来。那么我们看看SpringBoot是如何进行自动配置和启动的。SpringBoot通过main方法启动SpringApplication类的静态方法run()来启动项目。根据注释的意思,run方法从一个使用了默认配置的指定资源启动一个SpringApplication并返回ApplicationContext对象,这个默认配置如何指定呢?这个默认配置来源于@SpringBootApplication注解,这个注解是个复

    2022年8月20日
    4
  • python基础(5)字典[通俗易懂]

    python基础(5)字典[通俗易懂]字典字典的key和value一一对应的,字典是可变的,也是有序的(python3.6版本开始字典有序),可迭代的增加元素当key不存在时,直接赋值a={"status"

    2022年7月28日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号