C++和C#混合编程,C#调用C++生成的dll以及字符串传递

使用VS2017把C++项目打包成dll,并暴露函数。
1、创建下图类型的项目

在这里插入图片描述
默认生成的是这样的,我们在Dll3.cpp中写函数就行。
在这里插入图片描述

2、创建、或者从外部引入C++文件。

注意:要在每个cpp文件的头部都加上 #include “stdafx.h”,而且一定要在首行。不然会报错。
注意:若想要以c语言封装,图中标记的一定要存在。这里还是都加上吧。在这里插入图片描述
由于这里使用了strdup,所以生成dll时会报4996错误。
在这里插入图片描述
参考 https://blog.csdn.net/heimabuhei/article/details/79976270即可解决,好多函数都会报4996错误,用这个就行。

3、我演示的是传入和返回字符串

C++中代码

#include "stdafx.h"
#include<string>
#include<iostream>

using namespace std;
extern "C" _declspec(dllexport)const char* show_and_return(char* s) {

	string str = s;
	cout << s << "\n";
	//下面的string转const char* 代码很重要。我找了好久,就这种好用
	string return_str = "hello word1\nhello word2\n";
	const char* return_char;
	return_char = strdup(return_str.c_str());
	return return_char;
}

为了方便看,提前贴出C#调用与dll交互的代码。我用的时WPF程序。

//部分代码
    public partial class MainWindow : Window
    {
//为了方便演示,我就直接写了C++生成的dll的绝对路径。
     [DllImport("C:\\Users\\Administrator\\source\\repos\\Dll3\\Debug\\Dll3.dll", EntryPoint = "show_and_return",  CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr show_and_return(string a);

        public MainWindow()
        {

            InitializeComponent();
            string s = "传输参数,由C++打印";
            IntPtr p = show_and_return(s);
            string str_out = Marshal.PtrToStringAnsi(p);
            Console.WriteLine(str_out);

        }
    }

这里有下面几点需要注意:
(1)C++ 函数的参数使用char类型的形参接收外部传入的字符串。
然后C#调用dll时传入的参数类型时
string就可以。
(2)C++返回字符串类型为 const char
,这里一定要注意。我试过 如果返回值参数为string,C#调用dll时会报错。
下面还需要注意:我们可能在C++用的是string类型,但是由于我们的返回值类型是const char*,所以要把进行转换,经过我的尝试,使用

1、
str.c_str();
2、
str.data();
3、以及这篇文章(https://blog.csdn.net/mpp_king/article/details/88763120)的方法都有问题。

使用前两种方法,C#获得的是空值。使用三种方法,返回的字符串仍有乱码。

通过参考这篇https://blog.csdn.net/weixin_40647819/article/details/108245474文章,使用strdup()函数解决。

然后C#接收时用IntPtr类型接收,然后转化为c#中的string类型。

4、C++代码写完后,根据下图生成dll

在这里插入图片描述

C#中调用

我直接创建的是一个WPF项目。这个无所谓,只要是C#项目就可以。下面说下我遇到的问题。
代码如下,和上面一样。

//部分代码
    public partial class MainWindow : Window
    {
//为了方便演示,我就直接写了C++生成的dll的绝对路径。
     [DllImport("C:\\Users\\Administrator\\source\\repos\\Dll3\\Debug\\Dll3.dll", EntryPoint = "show_and_return",  CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr show_and_return(string a);

        public MainWindow()
        {

            InitializeComponent();
            string s = "传输参数,由C++打印";
            IntPtr p = show_and_return(s);
            string str_out = Marshal.PtrToStringAnsi(p);
            Console.WriteLine(str_out);

        }
    }
1、因为我们生成dll的C++项目是x86的,所以C#项目也要是x86的。WPF默认是Anycpu,就会报错。所以需要改成x86。

在这里插入图片描述
**此外:**C++代码运行错误也会导致这个错误提示,所以也可以测试下,C++代码运行时,是否会有错误。我后来有一次是因为字符串访问冲突导致的该错误。

2、如果DllImport里不加CallingConvention = CallingConvention.Cdecl,这时会报下面的错误。

在这里插入图片描述

3、我发现在C#中直接用string类型也可以接收到字符串。
    public partial class MainWindow : Window
    {
        [DllImport("C:\\Users\\Administrator\\source\\repos\\Dll3\\Debug\\Dll3.dll", EntryPoint = "show_and_return",  CallingConvention = CallingConvention.Cdecl)]
        public static extern string show_and_return(string a);

        public MainWindow()
        {
            InitializeComponent();
            string s = "传输参数,由C++打印";
            string str = show_and_return(s);
            Console.WriteLine(str);
        }
    }
4、最后可以通过“输出”栏可以看见结果。

在这里插入图片描述
其中C++代码打印的那块,在关闭WPF窗体后,才会打印出来。

以上是我自己的总结,因为C++还是很久以前用过,有不对的地方请指出。

参考:
重要:https://blog.csdn.net/weixin_40647819/article/details/108245474
https://www.cnblogs.com/cyberarmy/p/10102350.html

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值