所以我正在编写一个纯 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/