模特网站模板滕州住房和城乡建设局网站

张小明 2026/1/11 9:21:55
模特网站模板,滕州住房和城乡建设局网站,自媒体营销的方式有哪些,商城app官方下载[Godot GDExtension] 记一次从 Mac 移植到 Windows 的 C 编译踩坑与完美解决方案 前言 最近在开发 Godot 4.x 的 GDExtension 插件#xff08;基于 godot-cpp#xff09;。在 Mac 上开发一切顺利#xff0c;代码编译运行完美。然而#xff0c;当我尝试将项目移植到 Windows…[Godot GDExtension] 记一次从 Mac 移植到 Windows 的 C 编译踩坑与完美解决方案前言最近在开发 Godot 4.x 的 GDExtension 插件基于godot-cpp。在 Mac 上开发一切顺利代码编译运行完美。然而当我尝试将项目移植到 Windows (MSVC) 环境时却遭遇了一连串的编译报错。从reinterpret_cast类型转换失败到_gde_UnexistingClass的诡异报错再到链接器找不到库文件。经过一番深入排查和代码精简最终找到了一套最优雅、最小化的配置方案。本文将总结这些“坑”及其背后的硬核原理并给出最终的解决方案。一、遇到的核心问题1. 编译器报错reinterpret_cast与_gde_UnexistingClass这是最让人头秃的报错。编译器提示无法将我的类成员函数指针转换为 Godot 内部需要的类型并且错误信息里出现了一个奇怪的类名_gde_UnexistingClass。error C2440: reinterpret_cast: cannot convert from void (PlayerGD::*)(...) to void (_gde_UnexistingClass::*)(...) note: Pointers to members have different representations原因分析并不是代码写错了而是 MSVC 编译器对“成员函数指针”的内存表示法进行了特定优化导致与 Godot 的通用模板不兼容详见下文深度解析。2. Windows 头文件污染 (min/max宏冲突)Windows 的windows.h默认定义了min和max宏这会直接破坏 Godot 和 C 标准库的模板代码。通常的做法是全局定义NOMINMAX宏但如果引入第三方库冲突依然难以避免。3. 链接错误LNK1181SCons 报错fatal error LNK1181: 无法打开输入文件“godot-cpp.windows.template_debug.x86_64.lib”。但目录下明明有这个文件只是多了个lib前缀。这是因为 MSVC 链接器不自动补全lib前缀。二、 硬核深度解析为什么必须用/vmg在解决问题的过程中添加/vmg编译选项是解决reinterpret_cast失败的关键。很多开发者虽然加上它解决了问题但并不清楚背后的原理。这里深入挖掘一下 MSVC 编译器的底层机制。1. C 成员函数指针的“多重标准”在 GCC 或 Clang (Linux/Mac) 编译器中C 类成员函数指针Member Function Pointer, MFP的大小通常是固定的例如 16 字节无论这个类是单继承还是多重继承。但在 Windows 的MSVC编译器中微软为了优化性能和内存采用了一种**“按需分配”**的策略单继承 (Single Inheritance)如果编译器判定你的类只有单继承如我的PlayerGD : public RefCounted它生成的函数指针非常小8 字节因为它只需要存函数地址。多重继承 (Multiple Inheritance)如果类有多重继承函数指针会变大16 字节因为还需要存储this指针的偏移量 (Adjustor)。虚拟继承 (Virtual Inheritance)如果是虚拟继承指针会变得更大24 字节。这种优化在普通开发中是好事但在 Godot GDExtension 开发中却成了噩梦。2. Godot 的“暴力”转换与冲突Godot 的 GDExtension 系统为了通用性需要一种统一的方式来存储所有类的函数指针。在 Godot 内部模板 (method_bind.hpp) 中它试图将我们自定义类的函数指针如PlayerGD::set_name强制转换 (reinterpret_cast) 为一个通用未定义类(_gde_UnexistingClass) 的函数指针。冲突发生了编译器视角我的PlayerGD是单继承所以它的函数指针是8 字节的“精简版”。Godot 视角目标类型_gde_UnexistingClass是前置声明编译器不知道其细节。为了安全MSVC 默认假设它是最复杂的虚拟继承所以期望的是24 字节的“完整版”指针。结果试图把一个 8 字节的数据强转为 24 字节的数据。MSVC 认为这会导致严重的内存访问错误数据布局不同因此报出了reinterpret_cast错误。3./vmg的作用/vmg(General Purpose Representation) 选项的作用就是告诉 MSVC 编译器“不要对成员函数指针做任何优化无论类是怎么继承的统统使用最通用、最完整最大的格式来表示函数指针。”加上这个选项后PlayerGD的成员函数指针也会变成通用的格式与 Godot 内部期望的格式达成一致类型转换自然就通过了。4. 常见疑问内部成员的继承会影响吗在排查过程中我曾产生疑惑“我的PlayerGD内部持有一个std::unique_ptrPlayer而这个内部的Player类继承自Role类。这会影响/vmg的配置吗”答案是完全不会。/vmg影响的是“指向PlayerGD类成员函数的指针”。编译器只关心PlayerGD自身的继承关系它继承自 Godot 的RefCounted。编译器完全不关心PlayerGD肚子里有什么成员变量比如Player指针。无论内部的Player继承自Role还是继承自其它十个类对于PlayerGD的函数指针大小没有任何影响。所以请放心使用/vmg它只修正函数指针的内存布局不会破坏你的业务逻辑对象。三、最佳实践解决方案基于以上分析我总结出了一套 Windows 下开发 GDExtension 的最佳配置。这套方案不仅解决了报错还通过架构设计优雅地规避了宏冲突。关键点一PIMPL 模式隔离 Windows 头文件为了避免windows.h的宏污染我使用了PIMPL (Pointer to Implementation)模式。在 GDExtension 的.h文件中只做前置声明不包含业务头文件。在.cpp文件中最后包含业务头文件。这样即使业务头文件引入了 Windows 宏也不会影响 Godot 的模板初始化。关键点二SConstruct 配置我们需要在 SCons 构建脚本中为 Windows 平台做三件事添加/vmg。添加/EHsc(开启标准 C 异常)。手动拼接库文件的lib前缀。四、最终代码展示1.SConstruct(构建脚本)# ... 前面省略 ...ifplatformmacos:# Mac 配置 ...env.Append(CCFLAGS[-fPIC,-stdc17,-g])env.Append(LINKFLAGS[-Wl,-undefined,dynamic_lookup])godot_cpp_lib_ext.aelifplatformwindows:godot_cpp_lib_ext.lib# 关键/vmg 解决成员指针大小问题/EHsc 开启异常env.Append(CCFLAGS[/std:c17,/utf-8,/EHsc,/Zc:__cplusplus,/vmg])# 定义基础宏 (此时甚至可以去掉 NOMINMAX如果你使用了 PIMPL)env.Append(CPPDEFINES[WIN32,_WIN32,_WINDOWS])ifARGUMENTS.get(debug_symbols,no)yes:env.Append(CCFLAGS[/Zi])env.Append(LINKFLAGS[/DEBUG])# 链接静态库逻辑godot_cpp_libos.path.join(godot_cpp_dir,bin,flibgodot-cpp.{godot_cpp_target}{godot_cpp_lib_ext})env.Append(LIBPATH[os.path.join(godot_cpp_dir,bin)])# 关键Windows下手动添加 lib 前缀lib_namefgodot-cpp.{godot_cpp_target}ifplatformwindows:lib_nameliblib_name env.Append(LIBS[lib_name])2.player_gd.h(头文件)使用std::unique_ptr和前置声明避免在此处包含业务逻辑头文件。#pragmaonce#includecstdint#includememory// 必须包含#includegodot_cpp/classes/ref_counted.hpp#includegodot_cpp/variant/string.hpp#includegodot_cpp/variant/utility_functions.hpp// PIMPL: 前置声明核心类不要 include 具体头文件// 这样可以物理隔离 Windows 头文件污染namespaceJrpgCoreSdk{classPlayer;}namespaceJrpgCoreSdk{classPlayerGD:publicgodot::RefCounted{GDCLASS(PlayerGD,godot::RefCounted);private:// 使用智能指针持有实现std::unique_ptrPlayerplayer_;protected:staticvoid_bind_methods();public:PlayerGD();~PlayerGD();// ... 方法声明 ...voidset_name(constgodot::Stringname);godot::Stringget_name()const;boolis_alive()const;};}3.player_gd.cpp(源文件)注意头文件包含顺序先包含自己的 GDExtension 头文件再包含 Godot 核心最后包含业务逻辑。// 1. 先包含自己的类定义 (让编译器先看到继承关系)#includegodot/player_gd.h// 2. 包含 Godot 核心#includegodot_cpp/core/class_db.hpp#includegodot_cpp/godot.hpp#includegodot_cpp/variant/utility_functions.hpp// 3. 最后包含业务逻辑 (此时 Godot 环境已建立不易冲突)#includejrpg/player.hnamespaceJrpgCoreSdk{PlayerGD::PlayerGD(){godot::UtilityFunctions::print(PlayerGD constructor called);// 初始化 PIMPLplayer_std::make_uniquePlayer();}// 必须在 cpp 中定义析构函数因为这里才知道 Player 的完整定义PlayerGD::~PlayerGD(){}// 代理调用核心逻辑 (注意使用 - )voidPlayerGD::set_name(constgodot::Stringname){player_-SetName(name.utf8().get_data());}boolPlayerGD::is_alive()const{returnplayer_-IsAlive();}voidPlayerGD::_bind_methods(){// 静态断言确保编译器真的看到了继承关系 (可选用于自检)static_assert(std::is_base_ofgodot::RefCounted,PlayerGD::value,Compiler cannot see inheritance!);// 得益于 /vmg这里不需要丑陋的 static_cast 了直接绑定即可godot::ClassDB::bind_method(godot::D_METHOD(set_name,name),PlayerGD::set_name);godot::ClassDB::bind_method(godot::D_METHOD(get_name),PlayerGD::get_name);godot::ClassDB::bind_method(godot::D_METHOD(is_alive),PlayerGD::is_alive);ADD_PROPERTY(godot::PropertyInfo(godot::Variant::STRING,name),set_name,get_name);}}总结在 Windows 上编译 Godot GDExtension遵循以下原则可以少走很多弯路必须加上/vmg这是为了解决 MSVC 成员指针表示法与 Godot 内部模板不兼容的问题。推荐 PIMPL 模式物理隔离 Windows 头文件从根本上解决宏冲突甚至不需要全局定义NOMINMAX。注意 Include 顺序.cpp中始终把自己的头文件放在第一位。手动拼接 Lib 名SCons 在 Windows 上需要手动处理库文件前缀。希望这篇文章能帮到同样在做 Godot C 开发的朋友们
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

郑州网站设计收费网站设置评价

一场突如其来的“公平革命”对于A股市场的普通投资者来说,面对技术装备精良、速度快如闪电的量化交易,常常有一种无力感,就好比“骑自行车追高铁”,无论如何努力,似乎总慢人一步。然而,一场震撼性的变革正在…

张小明 2026/1/3 15:20:45 网站建设

有关学校网站建设的建议网站开发及上线过程

掌握网络性能测试:iperf3双平台实战指南 【免费下载链接】iperf3网络测试工具-Win64AndroidAPK iperf3 网络测试工具 - Win64 Android APK 项目地址: https://gitcode.com/open-source-toolkit/01598 还在为网络速度不稳定而烦恼吗?iperf3网络性…

张小明 2025/12/28 22:00:50 网站建设

简单大气网站欣赏上海到北京机票

可编程 Web 开发:WCF 与现代 Web 技术的融合 在当今的 Web 开发领域,可编程 Web 代表了一系列旨在帮助开发者构建 Web 服务的技术。这些技术提供了多种方式来创建服务,其中服务导向架构(Service - Oriented Architecture)和表述性状态转移(REST)是两种常见的架构风格。…

张小明 2026/1/2 4:34:44 网站建设

大兴网站开发网站建设哪家好wordpress等待加载动画设置

互联网浏览器使用与邮件管理全攻略 一、弹窗窗口的处理 (一)弹窗的基本概念 弹窗和弹底广告是未经邀请,出现在浏览器窗口上方或下方的独立窗口。当访问网页时,任务栏出现新按钮,就可能有弹底广告。IE 的弹出窗口阻止程序可解决此问题,它默认开启,也可关闭或自定义设置…

张小明 2026/1/10 18:42:27 网站建设

企业网站成功案例网站开发json解析

9.4 实战:使用自己的数据集做 Stable Diffusion 的 LoRA 模型微调 引言 在上一节中,我们学习了如何使用现有的LoRA模型来定制Stable Diffusion的生成效果。然而,在许多实际应用场景中,我们可能需要针对特定的品牌、角色、风格或主题创建完全定制化的LoRA模型,这就需要我…

张小明 2025/12/29 1:02:02 网站建设

手机搭建网站软件下载手动升级 wordpress

目录一、Nginx简介1、Nginx是什么2、Nginx的优势3、Nginx下载二、Nginx的核心功能1、Nginx的反向代理什么是反向代理?简单的反向代理完整的基础配置反向代理解释2、Nginx的负载均衡。。什么是负载均衡?负载均衡算法(核心)3、Nginx…

张小明 2026/1/9 14:00:06 网站建设