• 通过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#

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

  • 相关阅读:
    git之clone
    gulp之sass 监听文件,自动编译
    cat命令
    centos安装yum源
    centos下wget: command not found的解决方法
    centos安装
    为什么很多公司招聘前端开发要求有 Linux / Unix 下的开发经验?
    ASP.NET MVC HtmlHelper用法集锦
    Html.Listbox的用法(实例)
    JSON入门实例
  • 原文地址:https://www.cnblogs.com/hont/p/4188964.html
Copyright © 2020-2023  润新知