首页 > 解决方案 > .NET DllImport 错误 EntryPointNotFoundException:将 AWS-Encryption-SDK 从 C 和 C++ 绑定到 C#

问题描述

我正在开发一个 .NET 5 项目,以使用 PInvoke、类型编组和 DllImportAttribute 将 AWS-Encryption-SDK 从 C 和 C++ 绑定到 C#。尝试调用此 C++ 函数时

aws_cryptosdk_keyring *Build(const Aws::String &generator_key_id, const Aws::Vector<Aws::String> &additional_key_ids = {}) const;

使用

[DllImport("aws-encryption-sdk-cpp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern aws_cryptosdk_keyring Build(string generator_key_id, string[] additional_key_ids = null);

我收到这个错误

System.EntryPointNotFoundException:无法在 DLL“aws-encryption-sdk-cpp.dll”中找到名为“Build”的入口点。

此函数的 dll 签名是

?Build@Builder@KmsKeyring@Cryptosdk@Aws@@QEBAPEAUaws_cryptosdk_keyring@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$vector@V? $basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator @D@2@@std@@@2@@7@@Z

到目前为止,我没有尝试过,因为 EntryPoint 是成功的。有没有人有任何想法?

标签: c#c++camazon-web-servicesdllimport

解决方案


扩展@jwezorek 的评论,C# 不知道如何调用 C++(类)函数,只知道 C 函数。这有几个原因,但我不会在这里讨论它们。

您需要(在 C++ 中)创建一个包装器,将每个 C++ 调用转换为“扁平化”C 调用。例如:

extern "C" void *createClass() {
  return (void*) new myClass();
}

extern "C" void destroyClass(void* self) {
  delete (myClass*) self;
}

extern "C" int callFunction1(void* self, int x, int y) {
  return ((myClass*) self)->function1(x, y);
}

您需要为每个类函数(加上构造函数和析构函数)编写一个函数。然后编译,将其链接到原始 C++ DLL 的库。然后在 C# 中,编写一个包装器来调用您的扁平类:

public class myClass : IDisposable {
  [DllImport("myFlattenedDll", EntryPoint="createClass")]
  public static extern IntPtr createClass();
  [DllImport("myFlattenedDll", EntryPoint="destroyClass")]
  public static extern void destroyClass(IntPtr self);
  [DllImport("myFlattenedDll", EntryPoint="callFunction1")]
  public static extern int callFunction1(IntPtr self, int x, int y);

  private IntPtr self;

  public myClass() {
    self = createClass();
  }

  ~myClass() {
    Dispose();
  }

  public virtual void Dispose() {
    lock (this) {
      destroyClass(self);
      GC.SuppressFinalize(this);
    }
  }

  public int callFunction1(int x, int y) {
    return callFunction1(self, x, y);
  }
}

您还应该研究一个名为SWIG的工具,它可以为您自动执行大量的包装器编码。


推荐阅读