三种C++转C#的方法(带指针转换、Demo源码)

第一种是直接添加c++项目引用

第二种是使用DllImport的方式

前两种可以参考:

两种c++转c#的方式_c++代码转c#-CSDN博客

第三种是本文需要介绍的,而且使用C#封装ffmpeg视频库的开源库FFmpeg.AutoGen也是使用下面的方法

本文测试环境:

win7

vistual studio 2012

步骤如下:

一   C++项目端操作

1.1 新建C++类库项目,名为Operation,选择Win32项目,如下图:

点击确定,弹出对话框,如下图:

点击下一步,接着弹出对话框,选择DLL,勾选空项目,如下图:

1.2  新建测试类FunctionOutPut,鼠标右键项目,选择     添加 /类,如下图:

在FunctionOutPut.cpp中输入如下代码,代码过于简单,就两个减法操作的函数,一个带指针而已,不做解释:

#include "FunctionOutPut.h"


FunctionOutPut::FunctionOutPut(void)
{
}


FunctionOutPut::~FunctionOutPut(void)
{
}

int sub(int a,int b){
	return a-b;
}

int pointer(int &a,int &b){
	return a-b;
}

1.3  添加一个名为FunctionOutput.def模块定义文件,添加方式如下,鼠标右键项目,选择   添加   / 新建项     后,弹出对话框,如下图:

并编辑如下:

1.4  生成项目,然后找到Debug(要找仔细咯,与C#的不同,它居然与项目文件同一个目录)目录下生成的Operation.dll,需要拷贝到C#的bin/Debug目录下

二    在同一个解决方案下新建C#的控制台项目,名为callDLL

2.1   由于在C#项目中使用指针,需要勾选项目中的  ‘运许不安全代码’ 选项,鼠标右键C#项目,选择属性,然后再弹出的对话框中勾选如下:

2.2  在主程序中编辑代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace callDLL
{
    class Program
    {
        //加载dll库,参数为dll库的名称,返回句柄
        [DllImport("kernel32")]
        public static extern IntPtr LoadLibrary(string lpFileName);
        //通过句柄释放dll库
        [DllImport("Kernel32")]
        public static extern bool FreeLibrary(IntPtr handle);
        //根据函数名输出库函数,返回函数的指针
        [DllImport("Kernel32")]
        public static extern IntPtr GetProcAddress(IntPtr handle, String funcname);
 
 
        //定义c++中sub方法对应的委托
        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate int CppSub(int a, int b);
 
        //定义c++中pointer方法对应的委托,注意如果带指针,需要在委托前面加上unsafe关机字
        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        unsafe public delegate int pointer(int *a,int *b);
       

        //因为Main方法中使用到指针,所以需要在Main方法前加上unsafe关键字
        unsafe static void Main(string[] args)
        {
            //加载c++对应的dll库
            IntPtr dll = LoadLibrary("Operation.dll");
            //获取c++对应的库函数sub
            IntPtr func = GetProcAddress(dll, "sub");
            //根据库函数sub获取委托实例
            CppSub sub = (CppSub)Marshal.GetDelegateForFunctionPointer(func, typeof(CppSub));
            //委托间接调用sub函数
            int res=sub(6, 3);
            Console.WriteLine(res);

            //获取c++对应的库函数pointer
            IntPtr func1 = GetProcAddress(dll, "pointer");
            //根据库函数pointer获取委托pointer实例
            pointer p = (pointer)Marshal.GetDelegateForFunctionPointer(func1, typeof(pointer));
            int a = 8;
            int b=3;
            int res1 = p(&a, &b);
            Console.WriteLine(res1);

            //释放dll库
            FreeLibrary(dll);
            Console.Read();

        }
    }
}

核心是通过委托来调用c++中对应的函数,同时需要注意的是,凡是涉及到使用指针相关的方法名或者定义委托的前面都要加上unsafe关键字,对应这方面的基础知识参考:https://www.cnblogs.com/lgx5/p/7353346.html

2.3  生成项目,把刚才生成的Operation.dll拷贝的bin/Debug目录下,并把项目设置为启动项目,然后运行效果图如下图:

使用这种方法封装webrtc音频增益模块可以参考:

使用C#封装webrtc音频增益模块_c# webrtc-CSDN博客

如果发生错误如下:

1  托管调试助手 "PInvokeStackImbalance":的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管

原因可能是:

你的委托定义的上方没有加:

[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]

2  不能使用非固定表达式中包含的固定大小缓冲区。请尝试使用 fixed 语句

原因是使用了指针进行赋值,却没有使用fixed语句,如下图分析:

3   未处理ArgumentNullException    值不能为 null

可能原因:1 没写def文件或者函数名没写对    2  C#和C++函数中传递的函数类型不对     3  有可能是平台设置不对,如C++的代码只能在64位的平台运行,如果不在C#端设置项目生成为64位的程序,也会报null异常。

4   尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

这样的错误我折腾了好久也没解决

Demo源码下载:http://zxy15914507674.gitee.io/shared_resource_name/Charp和C++间指针操作.rar

上面的链接被码云废掉了,直接去我的仓库下载:张祥裕/分享的资源名称,找打对应的

Charp和C++间指针操作.rar下载即可

 好了,本文到此结束,如果本文对你有帮助,资助2毛钱作为鼓励呗,穷逼一个,就当筹个网费吧

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxy2847225301

测试使用

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值