利用rdynamic编译选项解决tcc for windows的加载动态库问题

发布时间:2026/8/17 3:52:00
利用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选项。