c#调用c++程序方法和问题总结

本文介绍了C#调用C++方法的步骤,包括创建C++项目、新建头文件和源文件、编译生成dll文件,将其复制到C#项目中并引入调用。还分享了遇到的问题,如加载格式不正确、pinvok不对称等,通过使用x64文件夹下debug中的dll文件及统一平台设置解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C# 调用C++方法

静态方法调用

  1. 创建一个空的c++项目
    项目结构
    如上图为最终的c++项目结构
  2. 新建Demo.h头文件
#pragma once
extern "C" __declspec(dllexport) int sum(int a, int b);
class Demo {
public:
};

应用程序如果想要访问某dll中的函数,则该函数必须为导出函数。其中__declspec 标识符用来声明这是dll导出函数。

  1. 新建Demo.cpp源文件
#include <iostream>
#include "Demo.h"
using namespace std;


void output()
{
	cout << "hello world" << endl;
}

 int sum(int a, int b)
{
	output();
	return a + b;
}
  1. 编译
    右键点击项目目录-》属性,弹出下图所示弹框:
    属性界面
    配置平台为活动(x64) 配置类型选择 动态库.dll
    属性选择
    编译输出选择编译为C++代码
    最后点击生成-》生成新的解决方案。
  2. 找到c++项目所在文件夹-》x64 -》debug 中生成的dll文件。
    文件结构
    文件结构

注意: 一定要是x64文件夹下的debug中的.dll文件!!如果使用debug文件夹下的.dll文件c#调用会提示“试图加载不正确的文件格式”

  1. 复制dll文件到c#项目中的bin-》debug中。
    vsc文件结构

  2. c#引入dll文件,并调用函数。

using System;
using System.Runtime.InteropServices;

namespace vsc_demo
{
    class Program
    {
        [DllImport("Project1.dll")] //引入dll文件
        static extern int sum(int a ,int b); //声明使用的导出函数
        static void Main(string[] args)
        {
            sum(2,3); //调用函数
            Console.WriteLine("Hello World!");
        }
    }
}

遇到的问题

刚开始c#调用函数一直报试图加载格式不正确的函数或pinvok不对称什么的,按照网上的方法比如:dllimport()中添加CallingConvention = CallingConvention.Cdecl ,但是没有效果。后来想到文件目录X64中的debug跟文件目录下的debug文件夹中的文件可能是不一样的,然后使用项目目录-》x64 -》debug文件夹中的dll文件重新运行了一下,成功!

上述方法中c++代码在vs2019中编辑,c#代码在vscode中编辑。当我想在vs中开发c#窗体程序并调用c++程序时出现了以下问题:
错误代码展示
主要原因在于平台的问题,右键项目-》属性
属性
选择目标平台为x64,因为c++开发函数时选择的平台也是x64,ctrl+s保存设置然后重新运行即可成功。
成功运行

### C# 调用 C++ 程序或函数的方法:P/Invoke 互操作 C#C++ 的互操作可以通过多种方式实现,其中 P/Invoke(Platform Invocation Services)是常用的一种方法。它允许 C# 调用非托管代码,例如 C++ 编写的动态链接(DLL)。以下是关于如何在 C#调用 C++ 程序或函数的详细说明: #### 1. 基本概念 P/Invoke 是一种机制,用于从托管代码(如 C#)中调用非托管代码(如 C++ DLL)。通过 P/Invoke,可以将 C++ 函数导出为 DLL,并在 C# 中使用 `[DllImport]` 属性来调用这些函数[^1]。 #### 2. 定义导出 C++ 函数 在 C++ 中定义需要导出的函数时,通常需要使用 `extern "C"` `__declspec(dllexport)` 来确保函数以 C 风格导出,避免名称修饰问题。例如: ```cpp // MyCppLibrary.cpp extern "C" { __declspec(dllexport) int Add(int a, int b) { return a + b; } } ``` 此代码片段定义了一个简单的 `Add` 函数并将其导出为 DLL[^4]。 #### 3. 在 C# 中声明外部函数 在 C# 中,需要使用 `[DllImport]` 属性声明外部函数,并确保函数签名与 C++ 中的定义匹配。例如: ```csharp using System; using System.Runtime.InteropServices; class Program { // 使用 DllImport 属性声明 C++ 中的 Add 函数 [DllImport("MyCppLibrary.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int Add(int a, int b); static void Main() { int result = Add(5, 3); Console.WriteLine($"Result: {result}"); } } ``` 上述代码展示了如何在 C#调用 C++ 的 `Add` 函数。 #### 4. 处理回调函数 如果需要在 C++调用 C# 提供的回调函数,则需要在 C# 中定义一个委托类型,并将其传递给 C++ 函数。例如: ```cpp // MyCppLibrary.cpp typedef void (*Callback)(int); extern "C" { __declspec(dllexport) void RegisterCallback(Callback cb) { cb(42); } } ``` 对应的 C# 代码如下: ```csharp using System; using System.Runtime.InteropServices; class Program { // 定义与 C++ 回调函数签名匹配的委托 delegate void Callback(int value); [DllImport("MyCppLibrary.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void RegisterCallback(Callback callback); static void Main() { // 定义回调函数的实现 Callback myCallback = (value) => Console.WriteLine($"Callback received: {value}"); // 注册回调函数 RegisterCallback(myCallback); } } ``` 此示例展示了如何在 C# 中定义回调函数并将其传递给 C++[^2]。 #### 5. 注意事项 - **调用约定**:确保 C# 中的 `CallingConvention` 属性与 C++ 中的调用约定一致。常见的调用约定包括 `cdecl` `stdcall`。 - **数据类型映射**:C# C++ 的数据类型可能不完全一致,需要进行适当的转换。例如,C++ 中的 `char*` 可以映射为 C# 中的 `string` 或 `byte[]`。 - **异常处理**:C++ 中的异常不会自动传播到 C#,因此需要在 C++ 中进行适当的错误处理[^3]。 #### 6. 替代方案 除了 P/Invoke,还可以使用 C++/CLI(托管 C++)来实现 C# C++ 的互操作。C++/CLI 允许直接编写同时包含托管非托管代码的程序,从而简化互操作过程[^5]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值