1

我正在使用一个 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>

CreateActCtxActivateActCtx调用成功,但CoCreateInstance调用总是失败,返回 0x80070002,除非我将 DLL 放在C:\Program Files\Java...

是否有任何解决方案(除了使用 GAC)允许完全非托管的 C++ DLL 从任意已知位置的 DLL 加载和创建 C# 类的实例?

4

0 回答 0