【问题标题】:.NET DllImport error EntryPointNotFoundException: Binding AWS-Encryption-SDK from C and C++ to C#.NET DllImport 错误 EntryPointNotFoundException:将 AWS-Encryption-SDK 从 C 和 C++ 绑定到 C#
【发布时间】:2021-09-23 14:20:50
【问题描述】:

我正在开发一个 .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++”这样的语言,只有两种截然不同的语言C或C++。请不要像那样把两者混在一起。由于您尝试调用 C++ 函数,请删除 C 标记(以及所有提及“C/C++”)。
  • 你可能想要一个 extern "C" 围绕该函数,以防止名称损坏。
  • C# 不会神奇地知道如何处理 Aws::String 和 Aws::Vector。我的意思是你甚至可以从这样的 DLL 中导出 C++ 函数吗?一般要将DllImort转换成C#你需要一个C接口。您可以根据详细信息以各种方式将 C++ 封装在 C 函数接口中进行 AWS 调用。

标签: c# c++ c amazon-web-services dllimport


【解决方案1】:

扩展@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 的工具,它可以为您自动执行大量包装器编码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2010-11-09
    • 2012-04-19
    相关资源
    最近更新 更多