Visual Studio 2022 C++ 生成dll或so文件在windows或linux下用C#调用

背景

开发中我们基本使用windows系统比较快捷,但是部署的时候我们又希望使用linux比较便宜,硬件产商还仅提供了c++ sdk!因此我们做二次开发时需要Visual Studio 2022在windows下 C++ 生成dll或linux下生成so库文件供C#调用。

方案

需要确认一件事,目前c++这门语言不是跨平台的

第一个问题【C++生成dll在windows下使用C#调用】解决方案:

1、使用vs2022创建一个c++ window空项目,命名为DllForWindows

2、右键单击项目名称,选择属性,并在属性中修改输出类型为动态链接库dll

3、为我们的源文件目录添加一个main.cpp,内容如下:

extern "C" {
    __declspec(dllexport) int add(int x, int y) { return x + y; }
    __declspec(dllexport) int sub(int x, int y) { return x - y; }
    __declspec(dllexport) int mul(int x, int y) { return x * y; }
    __declspec(dllexport) int div(int x, int y) { return x / y; }
}

设置解决方案,配置平台生成

4、重新生成解决方案,就可以在Debug目录下找到我们的dll了

5、新建一个C# DotNet6 控制台空项目,命名为TestDllForWindows

6、把Program.cs代码修改为如下,然后重新生成一下解决方案,我们会生成bin目录

using System.Runtime.InteropServices;

namespace TestDllForWindows
{
    internal class Program
    {
        [DllImport("DllForWindows.dll")]
        public static extern int add(int x, int y);

        [DllImport("DllForWindows.dll")]
        public static extern int sub(int x, int y);

        [DllImport("DllForWindows.dll")]
        public static extern int mul(int x, int y);

        [DllImport("DllForWindows.dll")]
        public static extern int div(int x, int y);
        //原文链接:https://blog.csdn.net/qq_36694133/article/details/135863027

        static void Main(string[] args)
        {
            Console.WriteLine("C# 调用C++ 生成的dll动态库!");
            int x = 10, y = 5;
            Console.WriteLine(add(x, y));
            Console.WriteLine(sub(x, y));
            Console.WriteLine(mul(x, y));
            Console.WriteLine(div(x, y));
            Console.Read();
        }
    }
}

7、拷贝一份我们C++生成的dll到 bin/Debug/net6.0目录,或者把DllForWindows.dll拷贝到TestDllForWindows项目中,并设置DllForWindows.dll属性 复制到输出目录 --始终复制 生成操作----内容

8、运行我们的程序,可以看到结果如下

第二个问题【C++生成so在linux下使用C#调用】解决方案:

1、 使用vs2022创建一个c++ linux空项目,命名为SoForLinux

2、 新建main.cpp,内容如下**【与生成windows动态链接库不同,这里不需要__declspec(dllexport)修饰】**

cpp 复制代码
extern "C" {
	int add(int x, int y) { return x + y; }
	int sub(int x, int y) { return x - y; }
	int mul(int x, int y) { return x * y; }
	int div(int x, int y) { return x / y; }
}

3、 Linux 端准备工作

查看系统:uname -a或者uname -m

如果输出是 x86_64,那么您的系统是64位的。如果输出是 i686i386,那么您的系统是32位的。

    • 在虚拟机中的Linux系统内查看IP地址,linux输入ip addr|grep inet 回车

    • 在VS2022 中选择"工具------选项"

    • 选到"跨平台"

    • 添加远程连接

    • 主机名是IP地址

    • 端口不变

    • 用户名和密码是Linux系统对应的

    • 完成后点击 连接

    • 顶部可以看到连接成功,也可以选择对应的连接,选择 右边的验证,测试连接情况。

注意在使用Linux编译时可能会用到g++编译,需要安装g++编译器,还有就是远程连接可能由于防火墙问题vs2022无法连接

问题解决如下:

1、Linux系统中要先安装g++ ,这个g++是linux编译so库的工具,否则会提示 : "g++:command not found"

cpp 复制代码
Linux安装g++:

           bash: line 1: g++: command not found

           报错解释:
                   这个错误表明在Bash环境下尝试执行g++命令时,系统找不到g++这个程序。g++是GNU项目的一部分,是一个编译C++源代码的交叉编译器。
           解决方法:
 安装g++:
如果你使用的是基于Debian的系统(如Ubuntu),可以通过以下命令安装: 
sudo apt-get update
sudo apt-get install g++ 

如果你使用的是基于Red Hat的系统(如Fedora或CentOS),可以通过以下命令安装: 
sudo yum update
sudo yum install gcc-c++ 

如果你使用的是macOS,可以通过Homebrew安装:
brew install gcc 

如果已经安装了g++但仍然出现这个错误,可能是因为g++不在环境变量PATH中。可以通过以下命令查找g++的安装位置,并将其添加到PATH中:
export PATH=$PATH:/path/to/g++ 
替换/path/to/g++为g++实际的安装路径。 
确认安装后的g++版本与你的代码需求是否兼容。如果需要特定版本的g++,可能需要进一步安装或更新。 
如果你正在使用的是容器(如Docker)或者虚拟环境,确保在该环境中g++已经被正确安装。

2、远程连接可能由于防火墙问题vs2022无法连接

cpp 复制代码
关闭防火墙
在Ubuntu上启用并设置OpenSSH服务器,你需要执行以下步骤:

安装OpenSSH服务器软件包:
sudo apt update
sudo apt install openssh-server

服务安装后将自动启动。你可以通过运行以下命令来检查SSH服务的状态:
sudo systemctl status ssh

如果SSH服务没有启动,你可以使用以下命令启动它:
sudo systemctl start ssh

为了确保SSH服务在系统启动时自动启动,可以使用以下命令:
sudo systemctl enable ssh

(可选)如果需要修改SSH配置,编辑 /etc/ssh/sshd_config 文件,然后重启服务:
sudo systemctl restart ssh

确保Ubuntu防火墙允许SSH连接。默认情况下,OpenSSH服务器会监听端口22:
sudo ufw allow ssh
现在,你应该能够从远程客户端使用SSH来连接Ubuntu系统了。使用以下命令:
ssh [username]@[host-ip-address]
其中 [username] 是你的Ubuntu系统上的用户名,[host-ip-address] 是Ubuntu系统的IP地址。

4、右键单击项目名称,进入属性页,修改生成so文件

5、重新生成解决方案,可以在Debug文件夹下看到生成了lib前缀的so文件

查看Linux系统中,如下:

注意:上述在vs2022在linux中使用g++编译so库时,需要注意防火墙开放指定端口(默认22,也可以开放其他端口),需要提前在linux中安装g++编译so的环境。

5、新建一个C# DotNet6 控制台项目,名称为TestSoForLinux

6、把Program.cs文件内容修改为如下

cs 复制代码
using System.Runtime.InteropServices;
 
namespace TestDllForWindows
{
    internal class Program
    {
        [DllImport("libSoForLinux.so")]
        static extern int add(int x, int y);
        [DllImport("libSoForLinux.so")]
        static extern int sub(int x, int y);
        [DllImport("libSoForLinux.so")]
        static extern int mul(int x, int y);
        [DllImport("libSoForLinux.so")]
        static extern int div(int x, int y);
 
        static void Main(string[] args)
        {
            int x = 10, y = 5;
            Console.WriteLine(add(x, y));
            Console.WriteLine(sub(x, y));
            Console.WriteLine(mul(x, y));
            Console.WriteLine(div(x, y));
        }
    }
}

7、编译TestSoForLinux以后,右键单击项目名称,选择【发布】

8、部署模式改为【独立:这样linux系统不需要安装dotnet运行环境,我们打包的时候就带了进去,占用磁盘会稍大一点但是省心】,目标运行时为linux-x64【本文的系统是的ubuntu x64的运行环境,其他的根据实际视情况而定】,发布选项里勾选生成单个文件【相当于vs尽可能帮我们把应用和依赖包搞成一个文件】

9、保存发布配置,并点击发布,发布完毕后,我们点击打开文件夹

10、把生成的文件TestSoForLinux和C++生成的libSoForLinux.so都拷到我们的linux系统同一文件夹下

11、使用终端打开此目录,输入如下命令后回车【注意有个英文小数点,linux下好像需要指定目录位置】,运行结果如下:

cs 复制代码
./TestSoForLinux 

注意:在Linux中/home/linjie/Desktop/linux-x64下运行 ./TestSoForLinux 时可能会遇到权限问题,

提示 Permission denied,

解决:

cs 复制代码
sudo chmod 777 /home/linjie/Desktop/linux-x64

chmod 777 /home/linjie/Desktop/linux-x64/TestSoForLinux

hmod 777 /home/linjie/Desktop/linux-x64/libSoForLinux.so

在输入

./TestSoForLinux

以上就是Visual Studio 2022 C++ 生成dll或so文件,在windows下用C#调用dll动态库以及在linux下用C#调用so库的全部过程,在上述过程中需要注意几点

1、在windows下用C#调用dll动态库时,C++项目DllForWindows生成动态库时,需要设置DllForWindows位Win32 ,解决方案中设置X86,TestDllForWindows设置X86

2、vs2022中c++项目SoForLinux生成so库,在linux下用C#调用so库时,linux环境下需要先安装g++ ,在开放防火墙指定端口,默认22,也可以开放其他端口,因为vs2022编译C++的so库时是远程到Linux环境使用g++来编译so库的,windows环境下没法编译,只有在linux才可以,所以为了方便直接配置远程linux环境主机来使用g++编译so库,所以需要先安装g++ ,在开放防火墙指定端口,这样在vs2022中c++项目SoForLinux生成so库时可以设置SoForLinux 属性 配置属性 常规 远程生成计算机 中配置linux主机。同时需要设置c++项目SoForLinux 为 X64 位,而项目TestSoForLinuxX64位或者Any CPU都可以,发布时注意根据不同的部署环境选择对应的操作系统,例如本文时Linux Ubuntu X64系统,那么发布时就需要选择linux-64 为目标运行时,部署模式 一半选择 独立,这样发布时会把环境都打包进去,在linu环境下运行时,就不需要在额外安装运行时了。****

参考链接:Visual Studio 2022 C++ 生成dll或so文件在windows或linux下用C#调用_visual studio 2022 编译 so-CSDN博客

参考链接:【编译部署】使用Visual Studio编译Linux平台程序/动态库(远程连接)_vs编译linux程序-CSDN博客

参考链接:https://blog.csdn.net/wq57885/article/details/90553021/

相关推荐
Cooloooo10 分钟前
树的重构【东北大学oj数据结构7-4】C++
数据结构·c++·重构
小比卡丘2 小时前
【C++初阶】第8课—标准模板库STL(string_2)
开发语言·c++
溟洵3 小时前
【C++第三方库】快速上手---轻量级数据库SQLite和单元测试工具Gtest
数据库·c++·后端·单元测试·sqlite
孙同学_3 小时前
【C++】- 掌握STL List类:带你探索双向链表的魅力
c++·链表·list
黑码农3336 小时前
C++day3
开发语言·c++·算法
物联网牛七七6 小时前
11、多态
c++·多态·虚函数·純虚函数
lin zaixi()8 小时前
C++ STL 快速实现全排列
数据结构·c++·算法
遮天华月9 小时前
C++ 运算符重载详解
c++·学习·算法
宏阳李老师9 小时前
2024-12 GESP C++ 二级试题及答案解析
开发语言·数据结构·c++·算法·青少年编程·gesp·csp
迷路爸爸18010 小时前
如何在Windows与Linux(Ubuntu/CentOS)之间配置SSH免密登录
linux·windows·ubuntu