利用rdynamic编译选项解决tcc for windows的加载动态库问题 上文写到tcc for windows编译的so不能被luajit插件调用。再来试其他编译器。在windows用mingw 编译的so能被luajit插件调用。C:\Users\ltcd\d C:\dss C:\dset pathC:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Users\lt\AppData\Local\Programs\Python\Python313\Scripts\;C:\Users\lt\AppData\Local\Programs\Python\Python313\;C:\Users\lt\AppData\Local\Microsoft\WindowsApps;;C:\Users\lt\AppData\Local\Programs\Ollama;C:\Users\lt\.dotnet\tools;C:\d\mingw64\bin;C:\d\pypy C:\dgcc -shared -fPIC -o libsudoku_c6.so sudoku_solve.c C:\dduckdb155 DuckDB v1.5.5 (Variegata) Enter .help for usage hints. memory D load luajit; memory D SELECT * FROM luajit_module(mode : compile, sql_name : sudoku_c, source : return function(p) local ffi require(ffi) ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib ffi.load(./libsudoku_c6.so) local buf ffi.new(char[82]) local rc lib.sudoku_solve(p, buf) if rc ~ 1 then return NULL end return ffi.string(buf) end ); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ memory D SELECT luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020); ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ memory D SELECT * FROM luajit_module(mode : compile, sql_name : sudoku_c, source : return function(p) local ffi require(ffi) ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib ffi.load(./libsudoku_c.so) local buf ffi.new(char[82]) local rc lib.sudoku_solve(p, buf) if rc ~ 1 then return NULL end return ffi.string(buf) end ); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ memory D SELECT luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020); ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ NULL │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘ memory D在luajit中调试较难改用一个c源文件来在tcc中调试。#includestdio.hintsudoku_solve(constchar*p,char*out);intmain(){// 一个简单的数独题目constchar*puzzle530070000600195000098000060800060003400803001700020006060000280000419005000080079;charsolution[82];if(sudoku_solve(puzzle,solution)){printf(Solution found!\n);for(inti0;i9;i){for(intj0;j9;j){printf(%c ,solution[i*9j]);}printf(\n);}}else{printf(No solution exists.\n);}return0;}神奇tcc编译main函数源文件时不识别tcc 自己编的so文件却能识别mingw编的。C:\dtcc\tcc callsd.c ./libsudoku_c.so -o callsdt.exe tcc: error: undefined symbol sudoku_solve C:\dtcc\tcc callsd.c ./libsudoku_c6.so -o callsdt.exe C:\dcallsdt Solution found! 5 3 4 6 7 8 9 1 2查看tcc命令行帮助信息解决了。windows中tcc同时用-shared和rdynamic这两个选项编译就妥了。tcc --help -shared generate a shared library/dll -rdynamic export all global symbols to dynamic linker C:\dtcc\tcc -shared -rdynamic -o libsudoku_c.dll dlxdll.c编译同时产生了libsudoku_c2.def文件内容如下LIBRARY libsudoku_c2.dll EXPORTS DllMain _dllstart _edata _end _etext sudoku_solve然后编译就不报tcc: error: undefined symbol sudoku_solve错了。C:\dtcc\tcc callsd.c ./libsudoku_c.dll -o callsdt2.exe C:\dcallsdt2.exe Solution found! 5 3 4 6 7 8 9 1 2 6 7 2 1 9 5 3 4 8 1 9 8 3 4 2 5 6 7 8 5 9 7 6 1 4 2 3 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9再用另一种算法的源文件编译dll也正确。C:\dtcc\tcc -shared -rdynamic -o libsudoku_c2.dll sudoku_solve.c C:\dtcc\tcc callsd.c ./libsudoku_c2.dll -o callsdt3.exe C:\dcallsdt3.exe Solution found! 5 3 4 6 7 8 9 1 2 6 7 2 1 9 5 3 4 8 1 9 8 3 4 2 5 6 7 8 5 9 7 6 1 4 2 3 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9这样编译出的动态库在luajit中也能正确识别。C:\dduckdb155 DuckDB v1.5.5 (Variegata) Enter .help for usage hints. memory D load luajit; memory D SELECT * FROM luajit_module(mode : compile, sql_name : sudoku_c, source : return function(p) local ffi require(ffi) ffi.cdef[[ int sudoku_solve(const char *p, char *out); ]] local lib ffi.load(./libsudoku_c2.dll) local buf ffi.new(char[82]) local rc lib.sudoku_solve(p, buf) if rc ~ 1 then return NULL end return ffi.string(buf) end ); ┌─────────┬─────────┬─────────┬─────────┬─────────┬──────────┐ │ ok │ mode │ phase │ message │ detail │ sql_name │ │ boolean │ varchar │ varchar │ varchar │ varchar │ varchar │ ├─────────┼─────────┼─────────┼─────────┼─────────┼──────────┤ │ true │ compile │ compile │ OK │ │ sudoku_c │ └─────────┴─────────┴─────────┴─────────┴─────────┴──────────┘ memory D SELECT luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020); ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ luajit_s(sudoku_c, 000001002000020030004500600007600050080090006100005800001004000070900003400030020) │ │ varchar │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 359461782716829534824573619947682351583197246162345897631254978275918463498736125 │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────┘这样tcc for windows的加载动态库问题解决了奇怪tcc在linux中编译不需要rdynamic选项。

相关新闻

最新新闻

错位相减法详解:等差乘等比数列求和的标准化解法与避坑指南

错位相减法详解:等差乘等比数列求和的标准化解法与避坑指南

1. 先搞清楚错位相减法到底在解决什么问题如果你正在准备高考数学,或者复习数列相关的考试,错位相减法是你绕不开的一个核心考点。它不是什么新概念,但每年都会在各类考试中以大题形式出现,分值不低。很多同学觉得它“套路固定&am…

2026/8/17 5:50:52
Ubuntu吉祥物全解析:从设计哲学到技术隐喻的视觉文化史

Ubuntu吉祥物全解析:从设计哲学到技术隐喻的视觉文化史

1. 项目概述:不止是“吉祥物”的视觉盛宴提起Ubuntu,很多人的第一反应是那个开源的Linux操作系统,是终端里敲下的sudo apt-get install,是服务器上稳定运行的后台服务。但今天,我们不聊代码,不谈配置&#…

2026/8/17 5:50:52
Java八大基本数据类型实战指南:从内存优化到避坑技巧

Java八大基本数据类型实战指南:从内存优化到避坑技巧

1. 项目概述:为什么“八大基本数据类型”是Java的基石刚接触Java那会儿,我觉得数据类型不就是int、double这些吗,有什么好学的?直到后来在项目里踩了坑,比如用int去存一个电商订单的总金额(单位是分&#x…

2026/8/17 5:50:52
Cadence 16.6 ODB++导出失败:从许可到环境的系统性排查与修复指南

Cadence 16.6 ODB++导出失败:从许可到环境的系统性排查与修复指南

1. 问题现象与核心痛点:为什么我的Cadence 16.6“罢工”了?如果你正在用Cadence 16.6版本,准备把辛苦画好的PCB设计文件导出为ODB格式,却发现菜单是灰的、点了没反应,或者干脆弹出一个看不懂的错误提示,然后…

2026/8/17 5:50:52
家庭网络AC+AP组网方案详解:从原理到TP-LINK AX3000M实战部署

家庭网络AC+AP组网方案详解:从原理到TP-LINK AX3000M实战部署

如果你正在为家庭或中小型办公室规划网络,面对市面上琳琅满目的路由器、Mesh套装、AP面板,是否感到无从下手?特别是当户型复杂、墙体较多,或者对网络稳定性、覆盖无死角有较高要求时,传统的单台高性能路由器或普通Mesh…

2026/8/17 5:50:52
计算机二级Excel高效备考:核心函数、数据透视表与避坑指南

计算机二级Excel高效备考:核心函数、数据透视表与避坑指南

1. 项目概述:一份“通关秘籍”的诞生与价值如果你正在备考计算机二级MS Office,尤其是被Excel部分的选择题搞得头大,那这份资料可能就是你的“救命稻草”。我当初备考时,市面上资料要么是零散的题库,要么是只有答案没有…

2026/8/17 5:45:51