c# - gcroot 和/clr 混合模式和 C++ 包装器是从纯 C 到 C# 的最短路径吗?

标签 c# c clr

所以我正在编写一个纯 C 的插件 DLL(以及一堆外国包含),但大部分实际代码都在现有的 C# 类库中。我正在寻找从 C(不是 C++)到 C# 的最短路径。外部包含不是 C++ 安全的。

C++ 的示例有很多,纯 C 的示例不多。

看来我应该能够将整个 DLL 编译为/clr,但不能将 C 编译为;然后在同一个 DLL 中包含一个 C++ 包装器,该包装器提供一个 C API,但包含调用 C# 类的托管代码。

因此,实例化 C# 类并在 C++ 类的 gcroot 中挂起它,并将 C++ 类指针作为 void* 返回给 C 代码以供将来调用使用。

有相当多的细节需要正确处理,但没有那么多代码。有没有更好的办法?


觉得是时候添加一些代码了。

// Wrapper.h
#pragma once
// API for call by C
#ifdef __cplusplus
extern "C" {
#endif
    void* wrap_create();
    void wrap_doit(void* wrapper, char* input, char* output, int maxlen);
#ifdef __cplusplus
}
#endif

// Wrapper.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <vcclr.h>
#include "Wrapper.h"
using namespace System;

class Wrapper {
public:
    gcroot<Wrappee::Evaluator^> eval;
    Wrapper() {}
};

void* wrap_create() {
    Wrapper* w = new Wrapper();
    w->eval = gcnew Wrappee::Evaluator();
    return w;
}

void wrap_doit(void* wrapper, char* input, char* output, int maxlen) {
    Wrapper* w = (Wrapper*)wrapper;
    String^ s = w->eval->Doit(gcnew String(input));
    pin_ptr<const wchar_t> wch = PtrToStringChars(s);
    wcstombs(output, wch, maxlen);
}

// Wrappee.cs
using System;
namespace Wrappee {
  public class Evaluator {
    string _s;
    public static Evaluator Create() {
      return new Evaluator {
        _s = "wrapped evaluator"
      };
    }

    public string Doit(string s) {
      return _s + ":" + s;
    }
  }
}

为什么那行不通?代码基于此链接:https://msdn.microsoft.com/EN-US/library/481fa11f%28v=VS.140,d=hv.2%29.aspx .


最佳答案

答案是否定的,那行不通。托管类依赖于 CLR 运行时,它需要由应用程序托管。对于自动发生的托管应用程序(mscoree.dll 在启动期间),但对于 native 应用程序,没有主机,因此没有 CLR。

所以我们必须提供一个。正如@hanspassant 有益地指出的那样,这是“反向 P/调用”,它确实是不同的。您必须通过 COM 托管接口(interface)到达那里,特别是 ICLRMetaHost

好消息是这里有一个示例来展示它是如何完成的:https://code.msdn.microsoft.com/windowsdesktop/CppHostCLR-e6581ee0 .

还有其他示例:搜索 CppHostCLR

关于c# - gcroot 和/clr 混合模式和 C++ 包装器是从纯 C 到 C# 的最短路径吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35787919/

相关文章:

c# - C# 上不允许出现默认参数说明符错误

c - 用值初始化数组(指针)

c - 将字符串 (R1) 拆分为 char b ='R' 和 int a=1

c# - LINQ 方法执行序列

c# - NUnit:为什么 Assert.Throws<T> 没有捕获我的 ArgumentNullException?

c# - 保存 xml 文件和 ConformanceLevel

c# - 从字符串XML读取数据

c - 函数末尾出现段错误

visual-studio-2010 - Visual Studio 2010 : Embed Interop Types

c++ - 我如何决定是否为新的 C++ 项目使用 ATL、MFC、Win32 或 CLR?