c# - 神秘段故障
问题描述
我的图书馆有一个非常特殊的问题。下面的简单示例完美运行。但更复杂的用例却没有。setStaticField 函数调用给出了段错误。稍后我将显示函数中的位置。
这是工作示例
int main()
{
Hunter::VM vm;
Hunter::Script* s = vm.createScript("test.dll");
Hunter::Class c = s->getClass("", "Entity");
c.setStaticField("test", vm.newString("YO!!!"));
return 0;
}
我的库的简短版本是这样的:它用于将 C# 嵌入到单声道框架中,尽管我很确定我的问题与单声道 API 无关。您首先创建一个 VM,我基本上是一个 MonoDomain 的包装器。然后,您从该 VM 中创建脚本。脚本本质上是围绕 MonoAssembly 及其匹配的 MonoImage 的包装器。然后你从一个脚本中得到一个 Class 对象,它是一个 MonoClass 的包装器。setStaticField 符合您的预期,它将 C# 类的静态成员变量设置为提供的值。同样,上面的示例功能完全。但下面的没有。
游戏.h
// includes and other inline variable declarations
inline Hunter::VM csharpVM;
// other includes
#include "../game.h"
// other functions
void loadScript(Scene* const a_scene, Json::Value a_data, entt::entity a_e)
{
std::string scriptPath = a_scene->path + a_data.asString();
scriptPath.erase(scriptPath.size() - 2, 2);
scriptPath += "dll";
Hunter::Script* s = csharpVM.createScript(scriptPath.c_str());
a_scene->registry.emplace<Hunter::Script*>(a_e, s);
Hunter::Class c = s->getClass("", "Part");
std::cout << "About to push: " << &a_e << std::endl;
c.setStaticField("partID", static_cast<void*>(&a_e));
int sceneInt = reinterpret_cast<int>(a_scene);
c.setStaticField("scenePtr", &sceneInt);
std::cout << "Scene pointer: " << a_scene << "\nScene int: " << sceneInt << "\nScene Pointer back: " << reinterpret_cast<Scene*>(sceneInt) << std::endl;
s->getStaticMethod("Part:onCreate()")();
}
这个函数应该使用我的 Hunter 库加载到脚本中,附加到一个 Entt 实体(我使用的 ECS。这里没有导入。),将它的 partID 字段设置为它在 Entt 中的 ID,将它的 scenePtr 成员设置为指向它所属的场景,然后调用它的 onCreate 方法。方法调用有效。但是两个 setStaticField 调用都在函数的最后一行给出了段错误(设置值的实际调用)
void setStaticField(const char* const a_name, void* a_value)
{
MonoClassField* const field = mono_class_get_field_from_name(this->m_class, a_name);
if (!field)
{
std::cerr << "Field error! Name: " << a_name << std::endl;
}
MonoVTable* const vtable = mono_class_vtable(mono_get_root_domain(), this->m_class);
if (!vtable)
{
std::cerr << "VTable error! Name: " << a_name << std::endl;
}
std::cout << "About to send: " << a_value << std::endl;
mono_field_static_set_value(vtable, field, a_value);
}
最后,这是这里使用的两个 C# 脚本。似乎链接在一起并正确继承。
using System;
class Part : Game.PartBasic
{
public static void onCreate()
{
Console.WriteLine("ScenePtr: ");
Console.WriteLine(scenePtr);
setPosition(500, 500);
}
public static void onUpdate()
{
}
public static void onDestroy()
{
}
}
using System;
using System.Runtime.CompilerServices;
namespace Game
{
public class PartBasic
{
public static uint partID;
public static int scenePtr;
public static void setPosition(int a_x, int a_y, int a_partID = -1)
{
if (a_partID == -1)
{
GameInternals.setPosition(a_x, a_y, partID, scenePtr);
}else{
GameInternals.setPosition(a_x, a_y, Convert.ToUInt32(a_partID), scenePtr);
}
}
}
class GameInternals
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static void setPosition(int a_x, int a_y, uint a_partID, int scenePtr);
}
}
同样,这一切都适用于顶级示例,但不适用于此处。任何帮助将不胜感激!
解决方案
推荐阅读
- c# - 如何在运行时为嵌套属性构建类映射
- javascript - 如何使用嵌套循环 (.each) 在 Cypress 中迭代 HTML 表
- mysql - 在 Mysql 中,以前的用户在 droppng 并创建同名后可以访问数据库
- c# - 按键输入后需要循环
- javascript - Laravel & React:限制对已识别用户的访问
- gis - 当 SpatialFilter 在基础和候选之间建立空间关系时,如果在 FME 中一对多,它是如何链接的
- swift - 将 sqlite 预加载到核心数据
- javascript - 滚动页面或滑动滑块时,如何停止使用 react-youtube 包嵌入的视频?
- javascript - 在Javascript中从数组中选择并删除随机单词
- mysql - Visual Studio 2019中EntityFramework向导连接MySql的问题如何解决?