libdxfrw 实战:用 C++ 免费解析 DXF/DWG 图纸,30 分钟跑通读取与转换 📅 发布时间:2026/8/20 16:05:11 👁 浏览次数: libdxfrw 实战用 C 免费解析 DXF/DWG 图纸30 分钟跑通读取与转换【免费下载链接】libdxfrwC library to read and write DXF/DWG files项目地址: https://gitcode.com/gh_mirrors/li/libdxfrw周五下午 5:40甲方把一张.dwg图纸甩进工作群附言明天上线前把里面的标注文字全部导出来。你的 C 程序只认 DXF临时装 AutoCAD 要授权商用图纸 SDK 一年几万块。如果你也是做 CAD 二次开发、图纸数据提取或设备对接的开发者libdxfrw这个免费开源的 C 库就是为这个场景准备的——它既能读写 DXF 文件ASCII 与二进制两种格式也能解析从 R14 到 V2015 的 DWG 文件。这篇文章带你走完装库 → 跑通最小示例 → 应用到真实场景的完整链路所有命令和代码都按仓库现状核对过可以直接复制。一句话定位一个库DXF 读写 DWG 解析libdxfrw是一个纯 C 编写的开源库核心能力可以压缩成三句话DXF 读写支持 R12、2000、2004、2007、2010 五个版本ASCII 和二进制两种格式都能读、能写DWG 只读解析内置 5 个按版本拆分的阅读器15/18/21/24/27覆盖 R14、R2004、R2007、R2010、R2013/R2015自带两个完整工具dwg2dxf格式转换和dwg2text文字提取既是生产力工具也是最好的 API 教学样例。在动手之前先把边界讲清楚免得你走弯路能力支持情况读 DXFASCII/二进制✅写 DXFASCII/二进制✅读 DWG✅R14 ~ V2015写 DWG❌ 明确不支持这是项目红线许可协议GPL v2 或更高版本商用注意传染性条款之所以把不能写 DWG提前说是因为我见过太多人抱着读了就该能写的预期白忙一场。后面所有场景都是在这个边界内展开的。上手主线从空目录到第一次成功运行第一步两条命令装好依赖并完成编译库的唯一硬依赖是 libiconv字符编码转换Debian/Ubuntu 系一条命令补齐sudo apt-get install build-essential cmake libiconv-hook-dev然后克隆仓库用 CMake 编译安装推荐三步走git clone https://gitcode.com/gh_mirrors/li/libdxfrw cd libdxfrw mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease cmake --build . sudo cmake --build . --target install运行结束后你会看到build/目录下生成了静态库libdxfrw.a安装后头文件在/usr/local/include/库文件在/usr/local/lib/libdxfrw.a。到这里库本身已经可以用了。顺带一提仓库还提供 Autotools 和 Visual Studiovs2013/下有 sln两种构建方式Windows 开发者可以直接开 sln 编译。第二步30 行最小读取器把图纸内容打印到终端libdxfrw最核心的设计是回调接口你写一个类继承DRW_Interface在关心的实体回调里处理数据然后把它交给dxfRW::read()驱动。解析器负责读文件你的类负责处理结果两者完全解耦——这正是后面所有场景能复用的根基。新建reader.cpp#include cstdio #include libdxfrw.h class MyReader : public DRW_Interface { public: // 头信息、表图层/线型等先不关心给空实现 virtual void addHeader(const DRW_Header*) override {} virtual void addLType(const DRW_LType) override {} virtual void addLayer(const DRW_Layer) override {} virtual void addDimStyle(const DRW_Dimstyle) override {} virtual void addVport(const DRW_Vport) override {} virtual void addTextStyle(const DRW_Textstyle) override {} virtual void addAppId(const DRW_AppId) override {} // 块记住进入/退出即可 virtual void addBlock(const DRW_Block) override {} virtual void setBlock(const int) override {} virtual void endBlock() override {} // 实体只打印我们关心的 virtual void addLine(const DRW_Line d) override { std::printf(LINE (%.2f, %.2f) - (%.2f, %.2f)\n, d.basePoint.x, d.basePoint.y, d.secPoint.x, d.secPoint.y); } virtual void addCircle(const DRW_Circle d) override { std::printf(CIRCLE center(%.2f, %.2f) r%.2f\n, d.basePoint.x, d.basePoint.y, d.radious); } // 注意其余 addPoint/addArc/addText/addMText 等 40 个纯虚函数 // 必须全部补空实现才能编译直接照抄 tests/test_basic.cpp 里的模板即可 }; int main(int argc, char** argv) { if (argc 2) { std::printf(usage: %s file.dxf\n, argv[0]); return 1; } MyReader reader; dxfRW dxf(argv[1]); if (!dxf.read(reader, false)) { // false 不做 2D 投影保留原始坐标 std::printf(读取失败%s\n, argv[1]); return 1; } return 0; }编译时链接静态库和 iconvg reader.cpp -I /usr/local/include /usr/local/lib/libdxfrw.a -liconv -o reader ./reader drawing.dxf跑起来你会看到每一条线段和圆都被打印成一行坐标。比如LINE (0.00, 0.00) - (100.00, 100.00) CIRCLE center(50.00, 50.00) r25.00如果你手上暂时没有 DXF 文件用下面第三步的写出器先造一个出来再回头喂给读取器闭环验证。第三步反向验证——3 分钟生成一个能打开的文件读取验证过了写方向同样简单。dxfRW::write()需要一个实现了write*系列回调的接口你在writeEntities()里往dxfRW上写实体即可#include libdxfrw.h class MyWriter : public DRW_Interface { public: dxfRW* dxf nullptr; bool exportFile(const char* name) { dxfRW out(name); dxf out; return out.write(this, DRW::AC1015, false); // 2000 版 ASCII 格式 } // add* 系列全部空实现照抄 tests/test_basic.cpp 模板 virtual void addHeader(const DRW_Header*) override {} virtual void addLayer(const DRW_Layer) override {} virtual void addBlock(const DRW_Block) override {} virtual void setBlock(const int) override {} virtual void endBlock() override {} virtual void addLine(const DRW_Line) override {} virtual void addCircle(const DRW_Circle) override {} // ... 其余 add* 同上 virtual void writeHeader(DRW_Header) override {} virtual void writeBlocks() override {} virtual void writeBlockRecords() override {} virtual void writeLTypes() override {} virtual void writeLayers() override {} virtual void writeTextstyles() override {} virtual void writeVports() override {} virtual void writeDimstyles() override {} virtual void writeAppId() override {} virtual void writeEntities() override { DRW_Line l; l.basePoint.x 0; l.basePoint.y 0; l.basePoint.z 0; l.secPoint.x 100; l.secPoint.y 100; l.secPoint.z 0; dxf-writeLine(l); DRW_Circle c; c.basePoint.x 50; c.basePoint.y 50; c.basePoint.z 0; c.radious 25; dxf-writeCircle(c); } }; int main() { MyWriter w; if (w.exportFile(out.dxf)) { std::printf(已生成 out.dxf\n); } return 0; }编译运行后out.dxf就出现在当前目录。因为 ASCII DXF 本质是文本文件你可以直接head out.dxf看到版本头$ACADVER与实体段内容也可以拖进任意 CAD 软件确认线段和圆都在。实战进阶三个真实场景拆解场景一DWG 转 DXF——一条命令解决甲方格式问题回到开头的场景。最省事的解法是用仓库自带的dwg2dxf工具。它不走 CMake用 Autotools 构建cd libdxfrw ./configure make构建完成后工具生成在dwg2dxf/目录下。转换命令很直观./dwg2dxf/dwg2dxf input.dwg -v2000 output.dxf-v参数控制输出 DXF 的版本-R12、-v2000、-v2004、-v2007、-v2010按下游软件支持程度选加-b输出二进制 DXF-y表示输出文件已存在时静默覆盖适合脚本化。运行结束你会看到命令行返回、output.dxf生成用file output.dxf能识别出 DXF 格式直接拖进 CAD 就能打开。如果有一整个目录的图纸要转用-B批量模式先写一个文本文件每行一个图纸的完整路径然后指定输出目录./dwg2dxf/dwg2dxf filelist.txt -B -v2004 -y /path/to/outdir/为什么能这样转这个工具内部就是用DRW_Interface回调把 DWG 读进来再把同一份数据写出去。读和写共用同一套数据结构所以天然实现了格式与版本的双重迁移。想深入理解直接读dwg2dxf/dx_iface.cpp——它是最浓缩的 API 教学。场景二批量抽取图纸文字绕开编码乱码标注、标题栏、技术要求这些文字是图纸里信息密度最高的部分。dwg2text工具就是干这个的把 DWG/DXF 里的 TEXT、MTEXT 逐条打印到终端配合管道就能直接入库./dwg2text/dwg2text drawing.dwg | tee text_out.txt运行后终端会滚动输出每条文字内容同时存进text_out.txt。这里藏着新手最容易误判的坑——编码。图纸里常见 CP932日文 Shift-JIS、CP936简体中文 GB2312、CP949韩文、CP950繁体 Big5。libdxfrw在src/intern/drw_textcodec.cpp里做了转换配合四张码表src/intern/drw_cptable*.h你拿到的std::string通常已经是 UTF-8。如果输出乱码优先检查源文件的 code page 声明而不是怀疑库本身——这是排障顺序问题能省你半小时。场景三格式无关的导入器——双入口的设计巧思dxfRW管 DXFdwgR管 DWG但两个类的方法签名完全一致都是read(DRW_Interface*, bool ext)。这意味着你可以写一个格式无关的导入器上层业务只认一种回调#include string #include libdxfrw.h #include libdwgr.h bool importFile(const char* path, DRW_Interface* cb) { std::string p(path); std::string ext p.substr(p.find_last_of(.) 1); if (ext dxf || ext DXF) return dxfRW(path).read(cb, false); if (ext dwg || ext DWG) return dwgR(path).read(cb, false); return false; }为什么这么设计因为 DXF 和 DWG 本质是同一套图纸数据模型的两种载体接口统一后你的图层管理、实体统计、坐标提取逻辑只需写一遍。上层业务完全不知道文件是 DXF 还是 DWG——这个抽象是整个库最值钱的部分dwg2dxf/dx_iface.cpp里就是这么用的。误区与边界清单新手最容易栽的 5 个地方错误做法正确做法说明只实现addLine/addCircle其余纯虚函数不写把DRW_Interface全部纯虚函数补空实现否则编译直接报未实现的纯虚函数用DRW::R2000当版本号用DRW::AC1015或AC1009/AC1018/AC1021/AC1024/AC1027版本枚举定义在src/drw_base.h是 AC 开头的编码read()的ext参数随手传true要原始 3D 坐标就传falsetrue会应用 extrusion 投影到 2D坐标值被改掉想用dxfRW写 DWG先写 DXF再用dwg2dxf转换库明确不支持 DWG 写入别在错误方向上花时间中文乱码就改源码先确认图纸 code page再检查输出端编码见场景二排障顺序决定效率调试技巧、测试与继续深入遇到解析失败先打开调试开关能省一半排查时间dxf.setDebug(DRW::DEBUG); // 或 dwg.setDebug(DRW::DEBUG);配合dwgR::getError()和dwgR::getVersion()能快速区分版本不支持返回BAD_VERSION和文件损坏返回BAD_READ_*系列错误码定义同样在src/drw_base.h。仓库自带完整测试套件覆盖实体读写、多段线、文字、表格、版本兼容、错误处理等场景cd build ctest你会看到十几个测试用例全部 PASS——这也是你改完代码后自检的基准。接下来想深入按这个顺序读源码效率最高src/drw_interface.h整个库的契约先读它再读实现dwg2dxf/与dwg2text/官方参考实现看完等于学会一半 APItests/每个用例都是怎么构造数据 怎么断言的示范README与SPECIFICATIONS.md构建细节与格式规格说明。贡献方式很常规fork 仓库、开分支、改代码、补测试、提 PR。项目基于 GPL v2 开源商用前记得先读COPYING评估许可影响。现在只差你的一条命令下次甲方再甩 DWG 过来你不需要临时装 AutoCAD也不用打听商用 SDK 的报价。libdxfrw已经把读 DXF、写 DXF、解析 DWG这三件事打包好还附带两个开箱即用的转换工具——你缺的只是把它跑起来的那一步。现在就动手克隆仓库编译然后把你手头那张图纸丢给dwg2dxf。十分钟后当它输出第一行坐标或第一份转换好的 DXF 时你会觉得这比买一年授权值多了。【免费下载链接】libdxfrwC library to read and write DXF/DWG files项目地址: https://gitcode.com/gh_mirrors/li/libdxfrw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考