当前位置: 首页 > news >正文

利用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选项。

http://www.jsqmd.com/news/1408656/

相关文章:

  • PowerMill自动编程实战:从模板宏到特征识别的效率革命
  • 2026 年马鞍山有实力的回转鼓风机厂家推荐几家,车间里这台老伙计,居然能帮工厂一年省下几十万电费?-远祥机械 - 行业推荐官[官方】--
  • 手机号码定位查询其实可以很简单:输 11 位号码,地图自动标出归属地
  • Kubernetes StorageClass配置与Local Path Provisioner实践
  • 超大PCB生产难在哪?揭秘制程与出货标准
  • 数据库迁移:goose与migrate工具
  • Windows系统下Kafka 3.3.2快速部署与一键启动实战指南
  • 从硬编码到规则引擎:Aviator表达式引擎在Java业务系统中的实战应用
  • Polkadot验证人奖励机制与收益优化指南
  • 从逻辑门到全可编程SoC:技术演进与软硬件协同设计实战
  • 2026 年新发布:抚宁本地豆包 AI 获客公司品牌电话,别再花冤枉钱获客了,这家人气爆火的AI服务商帮中小商家轻松拓客-抖企盈网络科技 - 行业鉴选官
  • VMware虚拟机磁盘在线扩容实战:从LVM原理到CentOS文件系统扩展
  • 双扩展卡尔曼滤波器在时变MVAR模型参数估计中的应用
  • Q-CueGraph:如何引导多模态大模型在视觉问答中精准聚焦关键信息
  • AI辅助数学研究实战:Claude与Python生态破解黎曼猜想探索
  • 蓝牙协议栈
  • 2026-08-16 GitHub 热点项目精选
  • 智能体编排:构建全模态AI应用的核心架构与实践指南
  • 多语言智能体公共空间实战评估:从静态指标到动态故障画像
  • 知识图谱增强RAG:解决传统向量检索的精确性与推理难题
  • SCP命令实战指南:从基础语法到高级运维应用
  • PCIE_FMC载板调试实战:从链路训练到驱动稳定,解决识别与性能难题
  • 手机号码定位免费开源指南:11位数字,3秒在地图上标出归属地
  • 上新:仰口景区海景民宿选哪家 - 品牌推广大师
  • 数学建模协会运营指南:从技术培训到组织管理的全流程实践
  • 2023年19款3D打印软件全解析:从建模到切片,构建你的完整工具链
  • Redis进阶:管道、事务与发布订阅
  • 《我.算子》体制异化与存在主义反抗
  • 3秒锁定位:免费开源的手机号码定位查询系统上手全攻略
  • 供应链建模数据预处理实战:Excel与SPSS协同清洗标准化流程