我正在使用一个 Java 应用程序,该应用程序可以使用可能包含本机代码的自定义包进行扩展,因此除了添加扩展 jar 的能力之外,我无法控制 Java 环境。
在这种情况下,我需要能够从 Java 扩展调用 C# 代码。这是以前使用无注册 COM 从纯本机上下文中使用的 C# 代码 - 工作正常。现在我需要能够从这个 Java 上下文中使用相同的代码,但遇到了似乎无法控制应该在哪里找到 DLL 的问题。要求将 DLL 安装到 JRE/JDK bin 目录中显然不是一种选择,并且要求将 DLL 注册到 GAC 中也不理想。
目前我希望将所有 DLL 依赖项打包到扩展 jar 中,并在运行时需要时加载(无需手动安装步骤)。
我希望我可以使用 Activation Context API 来使其正常工作,并测试了此代码的许多变体,DLL 位于D:\somepath\:
ACTCTX actctx = {sizeof(actctx)};
actctx.lpSource = "D:\\somepath\\dll.manifest";
actctx.lpAssemblyDirectory = "D:\\somepath\\";
actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
HANDLE hActCtx = CreateActCtx(&actctx);
ULONG_PTR ulpCookie = 0;
ActivateActCtx(hActCtx, &ulpCookie);
CoCreateInstance(...);
清单包含一个dependentAssembly,其中包含程序集的详细信息,其中包含对CoCreateInstance的调用引用的 C# 类。
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity name="[assemblyname]" processorArchitecture="msil" publicKeyToken="[token]" version="[version]" />
</dependentAssembly>
</dependency>
</assembly>
还尝试了使用 mt.exe 从 DLL 转储的这种格式的清单:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="[assemblyname]" version="[version]" publicKeyToken="[token]" processorArchitecture="msil"/>
<clrClass clsid="..." progid="..." threadingModel="Both" name="..." runtimeVersion="v4.0.30319"/>
...
<file name="[assemblyname].dll" hashalg="SHA1"/>
</assembly>
CreateActCtx和ActivateActCtx调用成功,但CoCreateInstance调用总是失败,返回 0x80070002,除非我将 DLL 放在C:\Program Files\Java...
是否有任何解决方案(除了使用 GAC)允许完全非托管的 C++ DLL 从任意已知位置的 DLL 加载和创建 C# 类的实例?