如何在Ubuntu下使用Python调用带参数的C#函数并获取返回结果
C# 适配Mono+Ubuntu16.04环境的ctypes调用实操指南
核心结论
- 这套实现的最终操作流畅度和你之前用C++
extern "C"导出的方案完全一致:Python侧全程用ctypes加载动态库、传参、拿返回值,无额外依赖 - 必须将C#代码编译为动态库(输出文件后缀为.so),不能编译为可执行exe,否则ctypes无法定位导出的函数
- 你之前遇到的“依赖不存在”报错,是因为照搬了Windows环境下基于第三方NuGet DllExport包的示例;在当前Mono环境下,完全不需要折腾NuGet拉取流程,系统源已提供所需的全部依赖
分步操作(完全匹配你当前的操作习惯,不需要额外学新工具)
1. 安装系统级依赖(替代NuGet拉包流程)
不需要手动找NuGet配置文件、不需要执行nuget restore,直接通过Ubuntu源安装现成的开发组件即可:
- 执行命令:
sudo apt install mono-devel mono-dll-export - 安装完成后,代码中用到的导出属性就已经在全局可用,不需要在项目目录下放任何依赖文件
2. 编写C#功能代码
新建一个名为MathLib.cs的文件,写入如下代码,不需要额外引用本地依赖文件:
using System; using System.Runtime.InteropServices; using Mono.DllExport; namespace SampleLib { public class NativeMethods { // 导出整数参数计算函数,调用约定和C++默认Cdecl对齐,避免传参错位 [DllExport("AddIntegers", CallingConvention = CallingConvention.Cdecl)] public static int Add(int a, int b) { return a + b; } // 导出字符串处理函数,测试非数值类型参数传递 [DllExport("GetStringLength", CallingConvention = CallingConvention.Cdecl)] public static int CalcStringLength(string input) { if (input == null) return -1; return input.Length; } } }
3. 编译生成动态库
你之前用csc编译exe的逻辑不需要变,只需要加两个编译参数,和之前的操作没有本质区别:
- 加
-target:library:指定csc生成动态库,而非可执行exe - 加
-out:libmathlib.so:指定输出文件后缀为.so,和C++编译的动态库格式完全兼容 - 加
-r:Mono.DllExport:告诉编译器引入全局安装的导出属性组件
完整编译命令:
csc -target:library -out:libmathlib.so -r:Mono.DllExport MathLib.cs
编译完成后,当前目录下会生成libmathlib.so文件,这就是可以被ctypes直接加载的动态库,和你之前用g编译的C so没有使用差异。
4. Python侧调用
Python侧的代码和你之前调用C++动态库的逻辑完全一致,不需要额外安装第三方包:
import ctypes # 加载动态库,操作和加载C++编译的so无区别 lib = ctypes.CDLL("./libmathlib.so") # 配置整数函数的参数和返回值类型 lib.AddIntegers.restype = ctypes.c_int lib.AddIntegers.argtypes = [ctypes.c_int, ctypes.c_int] calc_result = lib.AddIntegers(12, 23) print(f"整数计算结果:{calc_result}") # 输出35 # 配置字符串函数的参数和返回值类型 lib.GetStringLength.restype = ctypes.c_int lib.GetStringLength.argtypes = [ctypes.c_char_p] str_len = lib.GetStringLength(b"test csharp dll") print(f"字符串长度:{str_len}") # 输出15
常见操作问题
- 运行时需要手动用
mono启动动态库吗?
不需要。编译生成的so已经内嵌了必要的Mono运行时逻辑,Python加载时会自动完成初始化,和C++动态库的加载流程完全一致,不需要手动敲mono命令 - 为什么我之前直接抄NuGet版的示例代码会报错?
Windows环境下的DllExport是第三方NuGet包,需要手动在项目中引入依赖;但你当前的Mono环境对应的导出功能是系统预装组件,没有引入第三方NuGet的必要,照搬Windows的示例会因为缺少NuGet缓存的依赖文件触发报错 - 能不能直接用编译好的exe让Python调用?
不能。exe是可执行格式,没有对外暴露的导出函数表,ctypes无法定位到里面写的方法;只有编译为带导出表的动态库,才能实现和C++ extern方案一样的调用体验
内容的提问来源于stack exchange,提问作者Ri Di
相关产品推荐
相关产品推荐

