上文写到,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>
int sudoku_solve(const char *p, char *out);
int main() {
// 一个简单的数独题目
const char *puzzle = "530070000600195000098000060800060003400803001700020006060000280000419005000080079";
char solution[82];
if (sudoku_solve(puzzle, solution)) {
printf("Solution found!\\n");
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
printf("%c ", solution[i * 9 + j]);
}
printf("\\n");
}
} else {
printf("No solution exists.\\n");
}
return 0;
}
神奇,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选项。
网硕互联帮助中心



评论前必须登录!
注册