Delphi调用VC OBJ文件实战:混合编程实现算法复用与性能优化
1. 项目概述为什么要在Delphi里调用VC的OBJ如果你是一个长期在Windows平台上做客户端开发的“老炮”手头肯定有几个用Delphi写的祖传项目界面漂亮、逻辑稳定但就是某些核心算法或者硬件交互模块当年是用C特别是VC写的编译成了.obj或者.lib文件。现在想给老项目加点新功能或者优化一下性能重写整个模块不现实时间成本和风险都太高。这时候直接让Delphi去调用这些现成的C编译产物就成了最经济、最稳妥的技术路线。这不仅仅是“能用就行”而是一种非常务实的混合编程策略。Delphi在快速构建GUI、处理业务逻辑方面得天独厚而C在性能密集型计算、底层系统调用、复用现有成熟库比如某些图像处理、加密算法的C库方面优势明显。通过OBJ文件这座“桥”你可以把两者的优势焊接在一起既保住了Delphi项目的整体架构和投资又引入了C模块的强大能力。我最近就在一个工业数据采集项目里遇到了这个需求。上位机软件是Delphi 7写的稳定运行了十几年但现在需要增加一个实时频谱分析的功能。团队里有现成的、用Visual C 2019编写的、高度优化的FFT算法库已经编译成了COFF格式的OBJ文件。我的任务就是让Delphi主程序能无缝调用这个库。整个过程走下来踩了不少坑也总结了一套比较可靠的方法。这篇文章我就把这些实战经验从原理到细节完整地分享给你。2. 核心原理与前置知识跨越语言壁垒的约定在开始动手之前我们必须搞清楚DelphiPascal和C这里特指VC为什么能通过OBJ文件对话以及对话的前提条件是什么。这就像两个国家的人要做生意得先统一货币、语言和交易规则。2.1 OBJ文件编译后的“半成品”首先明确一点.obj文件对象文件不是最终的可执行文件.exe或.dll它是源代码文件.cpp经过编译器编译后生成的中间产物。它包含了机器代码函数体编译后的二进制指令。符号表记录了文件中定义和引用的函数名、变量名统称符号。重定位信息因为代码中可能包含对其他模块或数据的地址引用这些地址在链接前是未知的所以需要记录哪些地方需要后期“修正”。VC编译产生的OBJ文件默认遵循**COFFCommon Object File Format**格式这是Windows平台的标准对象文件格式。而Delphi的链接器ILINK32也完全支持链接COFF格式的OBJ文件。这是两者能够合作的技术基础。2.2 调用约定函数“打电话”的规则这是混合编程中最关键、也最容易出错的地方。调用约定规定了函数调用时参数是如何传递的、栈由谁清理、函数名如何修饰命名修饰等。Delphi和C默认的调用约定不同。__cdecl(C Declaration)C/C的默认约定除非在VC项目设置中更改。参数从右向左压栈由调用方清理栈。函数名修饰通常是在原函数名前加一个下划线如_MyFunction。它的优点是支持可变参数函数如printf。__stdcall(Standard Call)Windows API的标准约定也是Delphi中stdcall指令对应的约定。参数从右向左压栈由被调用方函数自身清理栈。函数名修饰更复杂通常是_MyFunction4后的数字表示参数总字节数。Delphi默认的调用约定是register寄存器传递但在声明外部函数时我们必须显式指定为stdcall来匹配VC中的__stdcall。关键决策点为了让Delphi能正确调用C函数我们必须在C源代码中将需要导出的函数显式声明为__stdcall调用约定。这是确保栈平衡不崩溃的前提。如果C函数是__cdecl而Delphi用stdcall去声明程序运行时几乎必然栈错误崩溃。2.3 命名修饰与extern CC支持函数重载编译器会对函数名进行复杂的“修饰”Name Mangling将参数类型等信息编码进最终链接时使用的符号名里。例如一个函数int Foo(int)可能被修饰成?FooYAHHZ。这个修饰后的名字对于Delphi来说是不可读的也极难在声明时写对。解决方案是在C头文件中用extern C包裹函数声明。这会告诉C编译器“按C语言的方式处理这些函数的链接符号”即禁止名称修饰并通常结合__stdcall产生一个简单、 predictable的符号名如_Foo4。一个标准的、供Delphi调用的C函数声明应该像这样// MyCppLib.h #ifdef __cplusplus extern C { #endif // 声明为 __stdcall 导出为裸函数名 int __stdcall AddTwoNumbers(int a, int b); void __stdcall ProcessBuffer(unsigned char* buffer, int bufferSize); #ifdef __cplusplus } #endif2.4 运行时库与内存管理这是一个深水区问题。VC编译OBJ时会链接特定的C运行时库如libcmt.lib多线程静态库。如果你的C函数内部调用了malloc/free、new/delete那么这些内存操作是在VC的运行时库环境中进行的。而Delphi有自己的内存管理器。黄金法则谁分配谁释放。绝对不要在Delphi中用FreeMem去释放一个由Cnew出来的指针反之亦然。这会导致堆损坏错误难以排查。安全的做法是接口设计隔离C函数不返回需要调用方管理内存的指针如字符串、复杂结构体。如果需要返回数据通常由调用方Delphi分配好缓冲区将指针和长度传给C函数去填充。提供配对的操作函数如果C函数返回了一个指向其内部动态分配内存的指针那么必须提供一个对应的C函数同样用extern C __stdcall声明来释放这块内存并在Delphi中调用这个释放函数。3. 实战步骤一准备C OBJ文件理论说再多不如动手。我们从一个最简单的例子开始让Delphi调用一个C函数计算两个整数的和。3.1 编写C源代码首先用Visual Studio这里以VS2019为例创建一个新的“空项目”项目类型选择“控制台应用”或“静态库”都可以因为我们最终只需要OBJ文件。创建MyMath.cpp和MyMath.h文件。MyMath.h(头文件)// MyMath.h #pragma once // 确保以C链接方式导出函数避免C名称修饰 #ifdef __cplusplus extern C { #endif // 使用 __stdcall 调用约定这是与Delphi stdcall兼容的关键 int __stdcall Add(int a, int b); // 一个稍微复杂点的例子处理字符串需谨慎 void __stdcall ConvertToUpper(char* str); #ifdef __cplusplus } #endifMyMath.cpp(源文件)// MyMath.cpp #include MyMath.h #include cctype // for toupper #include algorithm // 实现加法函数 int __stdcall Add(int a, int b) { return a b; } // 实现字符串转大写函数 // 注意这里假设str是以null结尾的C风格字符串。 // 由调用方(Delphi)保证传入的指针有效且内存可写。 void __stdcall ConvertToUpper(char* str) { if (str nullptr) return; while (*str) { *str static_castchar(std::toupper(static_castunsigned char(*str))); str; } }3.2 配置VC项目属性生成OBJ这一步的目标是生成一个干净的、可供Delphi链接器使用的.obj文件。打开项目属性在解决方案资源管理器中右键项目 - “属性”。配置为“Release”和“x86”因为大多数遗留Delphi项目是32位的所以平台选择“Win32”。确保配置是“Release”以获得优化代码。关键配置修改C/C - 高级 - 调用约定设置为“__stdcall (/Gz”。这会将项目中所有未显式指定调用约定的函数默认设为__stdcall。但我们已经在代码中显式声明了所以这个设置是双重保险。C/C - 代码生成 - 运行时库对于与Delphi混合编程我强烈推荐使用“多线程 (/MT)”。这是静态链接C运行时库生成的OBJ文件不依赖msvcrt.dll等动态库更易于部署减少了运行时依赖冲突的风险。链接器 - 常规 - 输出文件你可以看到默认是生成.exe。但我们不需要链接成可执行文件只需要OBJ。所以暂时不用管链接器设置因为我们不执行链接步骤。编译生成OBJ直接按CtrlShiftB编译项目。编译成功后去项目的x86\Release目录下如果是VS2019路径可能是x64\Release但请用Win32找到MyMath.obj文件。这就是我们需要的宝贝。实操心得在项目目录下单独建一个Output文件夹在项目属性 - 常规 - 输出目录中将其设置为$(SolutionDir)Output\。这样所有配置生成的OBJ文件都会集中到一个地方方便管理。另外务必记下你使用的VC编译器版本如VC 2019 v142因为不同版本的编译器生成的COFF格式可能有细微差异最好用相同或相近版本的Delphi如Delphi 10.4 Sydney对VC工具链支持较好进行链接。4. 实战步骤二在Delphi项目中链接与调用现在我们转到Delphi这边。这里以老当益壮的Delphi 7为例新版本XE系列、10.x原理完全相同只是IDE界面略有差异。4.1 创建Delphi项目与声明外部函数新建一个Delphi VCL应用程序。将上一步生成的MyMath.obj文件复制到你的Delphi项目目录下。在Delphi单元文件中如Unit1.pas的implementation部分之前{$R *.dfm}之后声明我们要使用的C函数。unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 class(TForm) Button1: TButton; Edit1: TEdit; Edit2: TEdit; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} // 关键步骤1声明外部OBJ文件中的函数 // 函数名必须与C中extern C __stdcall修饰后的名称匹配。 // 对于 __stdcallDelphi 使用 stdcall 指令。 // 参数类型要严格对应。Integer 对应 C int。 function Add(a, b: Integer): Integer; stdcall; external MyMath.obj; procedure ConvertToUpper(str: PAnsiChar); stdcall; external MyMath.obj; // 注意这里直接使用了MyMath.obj。Delphi链接器会在项目目录和库路径中查找它。 // 更规范的做法是使用 {$LINK} 指令见下文。4.2 使用{$LINK}指令链接OBJ文件上面直接在external后跟文件名的方法虽然简单但不够灵活。更规范、更推荐的做法是使用{$LINK}编译器指令它告诉链接器将指定的OBJ文件链接进最终的可执行文件。修改上面的声明部分implementation {$R *.dfm} // 关键步骤2使用 LINK 指令链接 OBJ 文件 {$LINK MyMath.obj} // 现在声明外部函数时不需要再指定文件名 function Add(a, b: Integer): Integer; stdcall; external; procedure ConvertToUpper(str: PAnsiChar); stdcall; external;{$LINK MyMath.obj}这一行至关重要它确保了MyMath.obj中的代码被物理地链接到你的.exe中。你可以将多个OBJ文件都通过{$LINK}指令加入。4.3 编写调用代码与测试现在我们可以在按钮点击事件中调用这些函数了。procedure TForm1.Button1Click(Sender: TObject); var Num1, Num2, Sum: Integer; TestStr: AnsiString; // 注意对于 char* 参数我们使用 AnsiString begin // 测试整数加法 Num1 : StrToIntDef(Edit1.Text, 0); Num2 : StrToIntDef(Edit2.Text, 0); Sum : Add(Num1, Num2); Label1.Caption : 结果 IntToStr(Sum); // 测试字符串转换 TestStr : hello, delphi vc!; ConvertToUpper(PAnsiChar(TestStr)); // 需要转换为 PAnsiChar 指针 ShowMessage(大写字符串 string(TestStr)); end;编译并运行。如果一切配置正确点击按钮你应该能看到加法计算结果并弹出一个消息框显示转换为大写的字符串。4.4 处理更复杂的数据类型结构体混合编程中传递结构体是常见需求。关键在于保证Delphi中的record默认packed与C中的struct通常需要#pragma pack(1)的内存布局字节对齐完全一致。C 端 (MyStruct.h)#pragma pack(push, 1) // 强制1字节对齐消除编译器填充与Delphi packed record匹配 extern C { typedef struct { int Id; double Value; char Name[32]; } MyDataStruct; void __stdcall ProcessStruct(MyDataStruct* data); } #pragma pack(pop) // 恢复默认对齐Delphi 端type // 使用 packed record 确保字节对齐与C端一致 TMyDataStruct packed record Id: Integer; Value: Double; Name: array[0..31] of AnsiChar; // 对应C char[32] end; PMyDataStruct ^TMyDataStruct; procedure ProcessStruct(data: PMyDataStruct); stdcall; external MyMath.obj;5. 进阶议题与深度避坑指南如果上面的简单例子能跑通恭喜你成功了一大半。但真实项目往往更复杂下面这些坑我几乎全踩过。5.1 名称修饰冲突与objdump工具的使用有时候你明明按照extern C __stdcall声明了函数在Delphi里链接时却报“未解决的外部符号”错误。这很可能是因为实际的符号名和你想象的不一样。解决方案使用VC自带的dumpbin.exe工具在VS开发人员命令提示符中可用查看OBJ文件导出的符号。dumpbin /SYMBOLS MyMath.obj在输出中寻找类似_Add8这样的符号。后面的数字是参数的总字节数两个int在32位下是8字节。这个_Add8才是你在Delphi中external后面应该跟的函数名如果使用name指令的话。在Delphi中你可以显式指定符号名function Add(a, b: Integer): Integer; stdcall; external name _Add8; // 或者如果C端是 __cdecl不推荐可能是 _Add使用dumpbin进行验证是解决链接器错误最直接的手段。5.2 C类与虚函数表的传递直接传递C类对象指针是极其危险的因为Delphi完全无法理解C的类布局、虚函数表vtable、构造函数/析构函数。绝对不要尝试。安全模式工厂函数与句柄在C端提供CreateInstance和DestroyInstance函数返回一个不透明的void*或HANDLE本质上就是this指针。所有对该对象实例的操作都通过这个“句柄”和一系列独立的C函数接口来完成。extern C { void* __stdcall CreateMyCalculator(); int __stdcall Calculate(void* handle, int x); void __stdcall DestroyMyCalculator(void* handle); }COM接口这是Windows平台上最规范、最强大的二进制兼容方案。将C类实现为COM组件Delphi通过CreateComObject和接口调用与之交互。这完全避免了链接和内存管理的烦恼但需要学习COM知识。5.3 内存对齐与字节序问题对齐如前所述对于结构体必须使用#pragma pack(1)和packed record来强制1字节对齐。对于包含double8字节的类型在某些默认对齐规则下如8字节对齐可能会导致Delphi和C结构体大小不一致引发内存访问错误。字节序x86/x64架构都是小端序所以基本不存在字节序问题。但如果你的代码涉及网络传输或与某些硬件可能是大端序交互则需要特别处理。5.4 调试技巧当程序崩溃时混合编程的崩溃Access Violation往往难以定位。启用完整调试信息在VC编译OBJ时在“C/C - 常规 - 调试信息格式”中选择“程序数据库 (/Zi)”。在Delphi中也生成调试信息Project - Options - Compiling - Debug information。使用MAP文件在Delphi链接器设置中生成MAP文件Project - Options - Linking - Map file。当程序崩溃时结合崩溃地址和MAP文件可以定位到是哪个模块是Delphi代码还是OBJ中的代码出了问题。分步验证先写一个最简单的C函数比如返回一个常量在Delphi中调用成功。然后逐步增加复杂度参数、返回值、结构体每步都测试可以快速隔离问题。6. 更优实践从OBJ到静态LIB直接管理一堆.obj文件比较零散。更好的做法是将所有相关的C函数编译后打包成一个静态库.lib文件。Delphi的链接器同样支持链接COFF格式的.lib文件。在VC中创建静态库项目新建项目选择“静态库(.lib)”。编写代码同样注意extern C和__stdcall。编译项目得到.lib文件。在Delphi中使用{$LINK MyCppLib.lib} // 链接静态库 function Add(a, b: Integer): Integer; stdcall; external;使用.lib的好处是所有相关OBJ都被封装在一个文件中管理更方便也避免了遗漏链接某个OBJ的尴尬。7. 常见问题速查表问题现象可能原因排查与解决链接错误Unresolved external ‘_Add8’1. OBJ文件未正确链接{$LINK}指令缺失或路径错误。2. C函数未用extern “C”导出名称被修饰。3. Delphi声明的函数名与OBJ中的符号名不匹配。1. 检查{$LINK}指令和文件路径。2. 用dumpbin /SYMBOLS查看OBJ中的实际符号名。3. 在Delphi中使用external name ‘_Add8’显式指定符号名。运行时崩溃Access Violation1.调用约定不匹配最常见。C用__cdeclDelphi用stdcall。2. 参数类型不匹配如int*vsPInteger。3. 结构体对齐方式不一致。4. 内存管理跨界在Delphi中释放Cnew的内存。1.确保C函数声明为__stdcallDelphi声明为stdcall。2. 仔细核对所有参数类型指针类型用正确的类型转换。3. 使用#pragma pack(1)和packed record。4. 遵循“谁分配谁释放”原则或提供配对的分配/释放函数。函数调用后栈损坏几乎肯定是调用约定不匹配导致栈平衡错误。同上首要检查调用约定。传递字符串后内容乱码或崩溃1. Delphi字符串类型转换错误。C需要char*应传递PAnsiChar。2. 尝试修改了字符串常量PChar(‘constant’)。3. 缓冲区溢出C函数写入了超出分配长度的内容。1. 对AnsiString使用PAnsiChar()转换对WideString对应wchar_t*使用PWideChar。2. 确保传入的是可写的内存如AnsiString变量。3. 在接口设计中明确缓冲区大小C函数进行边界检查。调试时无法进入C函数未生成或未包含C代码的调试信息PDB文件。在VC项目中启用/Zi编译选项并将生成的.pdb文件放在与.exe相同的目录下。最后我个人最深刻的体会是混合编程的成功90%取决于前期接口设计的严谨性。在动手写第一行C代码之前务必和团队或未来的自己明确约定好调用约定、数据类型映射、内存所有权、错误处理机制。把这些规则写成文档并创建一个简单的“契约测试”项目来验证。一旦接口稳定下来后续的开发和维护就会顺畅得多。这种技术就像一座精心设计的桥梁连通了两个强大的生态让你能在已有的Delphi资产上持续汲取C生态的强大能量。

相关新闻

Java、C、Python、PHP、C#五门主流编程语言核心特性与应用场景深度对比

Java、C、Python、PHP、C#五门主流编程语言核心特性与应用场景深度对比

1. 项目概述:为什么需要对比这五门语言?在技术社区里,关于“哪门语言最好”的争论几乎从未停歇。作为一个在软件行业摸爬滚打了十多年的老码农,我见过太多新手在Java、C、Python、PHP、C#这几门主流语言面前陷入选择困难。有人觉得…

2026/10/14 10:16:09 阅读更多 →
视频平台AI内容审核:从文本检测到多模态审核的后端架构复盘

视频平台AI内容审核:从文本检测到多模态审核的后端架构复盘

视频平台AI内容审核:从文本检测到多模态审核的后端架构复盘 一、背景与问题定义 视频平台的内容安全体系面临一个核心矛盾:内容量的指数级增长与审核人力资源的线性增长之间的巨大差距。传统的人工审核模式在日均百万级视频上传的场景下已难以为继——审…

2026/10/14 16:04:15 阅读更多 →
CDN技术演进:从MPLS管道到智能边缘计算

CDN技术演进:从MPLS管道到智能边缘计算

1. 管道与CDN的暗战:三万机房背后的技术博弈当你在深夜刷短视频时,是否想过为什么4K画质能流畅加载?当百万玩家同时在线游戏时,为何你的操作指令总能实时同步?这背后是一场涉及数万机房、横跨全球的"管道战争&quo…

2026/10/6 12:46:58 阅读更多 →

最新新闻

免费AI配音工具怎么选?媒小三配音与声音克隆功能介绍

免费AI配音工具怎么选?媒小三配音与声音克隆功能介绍

寻找免费 AI 配音工具时,很多人最关心三个问题:能不能免费体验、生成的声音是否自然,以及能否满足短视频日常创作需求。媒小三配音是一款结合 AI 配音、声音克隆和文案辅助功能的工具,提供网页、APP和微信小程序等使用入口。如果你…

2026/10/14 16:26:37 阅读更多 →
Mac Duo调试实战指南:用lidprobe命令行工具与os.Logger追踪传感器与渲染管线的每一毫秒

Mac Duo调试实战指南:用lidprobe命令行工具与os.Logger追踪传感器与渲染管线的每一毫秒

【免费下载链接】Mac-Duo Wish you could bring the iPhone Duo effect to your MacBook? 项目地址: https://gitcode.com/gh_mirrors/mac/Mac-Duo 点击查看 免费下载 Mac Duo 是一款把 iPhone Duo 闭盖特效带进 MacBook 的菜单栏应用:合上盖子&#x…

2026/10/14 16:26:37 阅读更多 →
家政服务小程序开发:核心功能与关键技术解析

家政服务小程序开发:核心功能与关键技术解析

1. 项目背景与市场需求分析最近两年,本地生活服务类小程序呈现爆发式增长,其中家政服务因其高频、刚需的特性成为热门赛道。我去年为某连锁家政品牌开发的预约系统,上线后订单量提升了37%,客户留存率提高了22%。这个成绩让我意识到…

2026/10/14 16:26:37 阅读更多 →
乔丹传奇:从篮球之神到商业偶像的五大成功要素

乔丹传奇:从篮球之神到商业偶像的五大成功要素

1. 为什么我们需要重新认识乔丹?1998年NBA总决赛第六场最后5.2秒,芝加哥公牛队83-86落后犹他爵士队。当篮球传到乔丹手中时,整个三角洲中心球馆的空气仿佛凝固了。这个穿着23号红色球衣的男人,用一记教科书般的急停跳投&#xff0…

2026/10/14 16:26:37 阅读更多 →
WuKongIM 有界云租约(Cloud Lease)暴露负载节点:Chat Lifecycle 的临时入口设计与实现解析

WuKongIM 有界云租约(Cloud Lease)暴露负载节点:Chat Lifecycle 的临时入口设计与实现解析

即时通讯后端 【免费下载链接】WuKongIM More than just IM 不只是即时通讯(IM) 项目地址: https://gitcode.com/gh_mirrors/wu/WuKongIM 点击查看 免费下载 导读 本文围绕 WuKongIM 仓库中的架构决策记录 ADR-0042(Expose the load node for the boun…

2026/10/14 16:26:37 阅读更多 →
AI生成内容检测与降AI工具实战评测

AI生成内容检测与降AI工具实战评测

1. 项目背景与需求解析在学术写作领域,AI生成内容的检测问题已成为全球学者关注的焦点。2023-2024年间,多所高校和期刊编辑部开始采用AI检测工具对投稿论文进行筛查,部分机构甚至明确要求论文AI生成率不得超过10%。这种技术监管的突然收紧&am…

2026/10/14 16:25:37 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →