【问题标题】:passing into c code from c# code in visual studio [duplicate]从 Visual Studio 中的 c# 代码传递到 c 代码 [重复]
【发布时间】:2017-10-31 11:10:42
【问题描述】:

我对如何从我的 c# 代码中引用我的 c 代码感到困惑。我已经阅读并意识到 DLL 很有用,但我不明白如何连接我的 dll。据我了解,我从我的 c 代码中制作了 dll?请帮忙

C#(视觉工作室代码)

public partial class Form1: Form{
  [DllImport("simple.dll", CallingConvention = CallingConvention.Cdec1)]
  public static extern void pinfo(string str);

  private void button1_Click(object sender, EventArgs e){
      pinfo("yay");
  }
}

C 代码 - simple.c

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
__declspec( dllexport ) void pinfo(char* str){
    printf("You are in the method %s\n, str);
}

int main(void){
}

我的问题是如何将 c 代码连接到 c# 代码,以便打印出“You are in the method yay”行?我不明白如何将 dll 文件链接到 Visual Studio 或如何创建 dll 文件。谢谢

【问题讨论】:

  • 您的代码对我来说看起来不错。当您尝试运行它时会发生什么? (请注意,您确实需要先导出 pinfo 函数)。使用__declspec( dllexport )
  • @dai 我添加了那行,我不确定如何运行它,因为我有一个 Visual Studio 项目,然后是一个与我的 Visual Studio 项目无关的 simple.c 文件,我不确定如何链接它们
  • 阅读有关如何创建 dll 的文档。你这样做了吗?

标签: c# c visual-studio dll dllimport


【解决方案1】:

让 P/Invoke (DllImport) 在 .NET 中工作有 3 个主要步骤:

  1. 从 C/C++ 项目中导出函数。

    在 Visual C++ 中,使用 __declspec( dllexport )extern "C" 修饰符分别告诉编译器将函数导出到 DLL 中,以便通过名称可见,而不是 mangle name 要么 - 否则编译器将完全删除该函数,如果它在项目中没有调用者(“死代码删除”)。函数也可以通过序数导出,这可能不是你感兴趣的。

  2. 确保您正在为相同的 ISA 构建。

    当您在 .NET 中使用 P/Invoke 时,您引用的 DLL 将被加载到宿主 .NET 进程中,因此 DLL 必须构建为与当前 .NET 进程相同的 CPU 指令集。 .NET 项目默认以AnyCPU 模式运行,但在最新版本的 Visual Studio 中,它们“更喜欢”32 位 (x86) 模式而不是 64 位 (x64 / AMD64)。为避免混淆,请确定您需要 32 位还是 64 位模式,并强制您的 .NET 项目仅为该 ISA 构建,然后将您的 C/C++ 项目也设置为为该 ISA 构建。

  3. 确保目标 DLL 文件位于 .NET 可执行文件的 PATH 中 - 通常这意味着只需将其放在与构建的 .NET 可执行文件相同的 bin 输出目录中。

    请注意,由于此 DLL 文件不是 .NET 程序集,因此没有“项目引用”或“程序集引用”的概念,因此您需要专门配置您的项目,以便 Visual Studio (MSBuild) 将复制 DLL文件到您的bin 文件夹 - 您可以通过将 DLL 文件添加到解决方案资源管理器中的 .NET 项目根目录,然后选择该文件并打开“属性”窗口并选择“构建操作:内容”来执行此操作。和“复制到输出目录:总是”。

关于“链接” - DLL 在编译时不链接 - 线索就在名称中:“动态链接”:链接由操作系统在运行时执行,而不是由编译器。

有关 P/Invoke 的更多信息,我建议阅读此 QA:Why are Cdecl calls often mismatched in the "standard" P/Invoke Convention?

【讨论】:

  • “请注意,您的 DllImport 声明不正确”中的所有内容都是错误的。非托管函数是 cdecl,默认封送处理很好。
  • 不,你错了。默认封送处理是使用流行字符集对以空字符结尾的字符数组。在桌面窗口上默认为 ANSI。全部记录在案。您应该阅读文档。
  • @DavidHeffernan 我的错误。我做了进一步的阅读,但我误读了文档。我已经从我的答案中删除了不正确的断言。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 2018-10-11
  • 2020-06-01
相关资源
最近更新 更多