ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

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

上文写到,tcc for windows编译的so不能被luajit插件调用。再来试其他编译器。
在windows用mingw 编译的so能被luajit插件调用。

C:\Users\lt>cd\d C:\d>ss C:\d>set path=C:\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:\d>gcc -shared -fPIC -o libsudoku_c6.so sudoku_solve.c C:\d>duckdb155 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中调试。

#include<stdio.h>intsudoku_solve(constchar*p,char*out);intmain(){// 一个简单的数独题目constchar*puzzle="530070000600195000098000060800060003400803001700020006060000280000419005000080079";charsolution[82];if(sudoku_solve(puzzle,solution)){printf("Solution found!\n");for(inti=0;i<9;i++){for(intj=0;j<9;j++){printf("%c ",solution[i*9+j]);}printf("\n");}}else{printf("No solution exists.\n");}return0;}

神奇,tcc编译main函数源文件时,不识别tcc 自己编的so文件,却能识别mingw编的。

C:\d>tcc\tcc callsd.c ./libsudoku_c.so -o callsdt.exe tcc: error: undefined symbol 'sudoku_solve' C:\d>tcc\tcc callsd.c ./libsudoku_c6.so -o callsdt.exe C:\d>callsdt 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:\d>tcc\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:\d>tcc\tcc callsd.c ./libsudoku_c.dll -o callsdt2.exe C:\d>callsdt2.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:\d>tcc\tcc -shared -rdynamic -o libsudoku_c2.dll sudoku_solve.c C:\d>tcc\tcc callsd.c ./libsudoku_c2.dll -o callsdt3.exe C:\d>callsdt3.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:\d>duckdb155 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选项。

返回列表