Windows下Julia调用C函数:MinGW正常MSBuild编译失败排查
解决MSBuild编译的64位DLL无法被Julia ccall调用的问题
你碰到的这个问题,本质是MinGW和MSVC(MSBuild背后的编译器)在C函数导出规则、符号处理上的差异导致的,再加上代码里的一个小细节放大了问题,咱们一步步搞定它:
核心问题分析
- 函数名大小写与声明不匹配:你的C代码里声明的是
int givemin(void);(全小写),但定义的是int giveMin(void)(驼峰式)。MinGW对符号大小写的处理比较宽松,或者编译时自动兼容了这种不一致,但MSVC会严格区分,这就导致MSBuild编译出的DLL里,导出的符号可能是givemin而非你Julia代码里调用的giveMin。 - MSVC默认不导出全局函数到DLL:MinGW编译DLL时,默认会导出未被
static修饰的全局函数,但MSVC需要显式标记函数为导出符号,否则函数不会被加入DLL的导出表,Julia自然找不到对应的函数。
具体解决方案
第一步:修正C代码的声明与定义一致性
先把函数的声明和定义统一成相同的命名,避免大小写问题:
// 统一使用驼峰命名的声明 int giveMin(void); int giveMin(void){ int minval = 0; return minval; }
第二步:让MSVC显式导出函数
有两种简单的方式实现:
方式1:在代码中添加导出标记
通过编译器宏判断,给MSVC编译的代码添加__declspec(dllexport)标记,其他编译器(比如MinGW)不需要:
#ifdef _MSC_VER // 针对MSVC,标记函数为DLL导出符号 #define EXPORT __declspec(dllexport) #else // 其他编译器不需要特殊标记 #define EXPORT #endif EXPORT int giveMin(void); EXPORT int giveMin(void){ int minval = 0; return minval; }
方式2:使用模块定义文件(.def)
如果不想修改C代码,可以创建一个名为libgetMinimum.def的文件,内容如下:
LIBRARY libgetMinimum EXPORTS giveMin @1
然后在你的CMakeLists.txt中,把这个.def文件关联到目标库:
add_library(libgetMinimum SHARED your_c_source_file.c libgetMinimum.def)
MSBuild会根据这个.def文件,把指定的函数导出到DLL中。
第三步:验证DLL的导出符号
可以用VS自带的dumpbin工具确认函数是否成功导出:
打开Visual Studio的开发者命令提示符,运行以下命令:
dumpbin /exports "C:\MyProjects\Julia-Tests\some-c-lib\build-msvc\src\libgetMinimum.dll"
如果输出结果里能看到giveMin这个符号,说明导出成功,此时再用Julia的ccall调用就不会报错了。
内容的提问来源于stack exchange,提问作者sruli
相关产品推荐
相关产品推荐

