Unity C#脚本调用WinRT组件构造函数触发NullReferenceException排查
问题描述
我正在开发一个基于C++/WinRT组件的Unity插件,在Unity C#脚本中尝试访问运行时类时抛出了NullReferenceException。以下是简化后的组件及Unity脚本代码:
WinRT RTClass.idl
namespace RuntimeComponent1 { runtimeclass HelperClass { HelperClass(); Int32 MyProperty; } [default_interface] runtimeclass RTClass { RTClass(); Int32 MyProperty; } }
WinRT HelperClass.h
#pragma once #include "HelperClass.g.h" namespace winrt::RuntimeComponent1::implementation { struct HelperClass: HelperClassT<HelperClass> { HelperClass(); int32_t MyProperty(); void MyProperty(int32_t value); }; } namespace winrt::RuntimeComponent1::factory_implementation { struct HelperClass: HelperClassT<HelperClass, implementation::HelperClass> { }; }
WinRT RTClass.h
#pragma once #include "RTClass.g.h" namespace winrt::RuntimeComponent1::implementation { struct RTClass : RTClassT<RTClass> { RTClass(); int32_t MyProperty(); void MyProperty(int32_t value); }; } namespace winrt::RuntimeComponent1::factory_implementation { struct RTClass : RTClassT<RTClass, implementation::RTClass> { }; }
WinRT HelperClass.cpp
#include "pch.h" #include "HelperClass.h" #include "HelperClass.g.cpp" namespace winrt::RuntimeComponent1::implementation { HelperClass::HelperClass() { } int32_t HelperClass::MyProperty() { throw hresult_not_implemented(); } void HelperClass::MyProperty(int32_t /* value */) { throw hresult_not_implemented(); } }
WinRT RTClass.cpp
#include "pch.h" #include "RTClass.h" #include "RTClass.g.cpp" namespace winrt::RuntimeComponent1::implementation { RTClass::RTClass() { // Do some stuff in the constructor } int32_t RTClass::MyProperty() { throw hresult_not_implemented(); } void RTClass::MyProperty(int32_t /* value */) { throw hresult_not_implemented(); } }
Unity脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; #if ENABLE_WINMD_SUPPORT using RuntimeComponent1; #endif public class TestScript : MonoBehaviour { #if ENABLE_WINMD_SUPPORT RTClass rt; #endif // Start is called before the first frame update void Start() { #if ENABLE_WINMD_SUPPORT rt = new RTClass(); // <--- NullReferenceException here // ... #endif } // Update is called once per frame void Update() { } }
相关环境与配置:
- WinRT组件以Debug模式针对ARM架构构建
- Unity版本:2021.3.27f1 LTS、2022.3.3f1 LTS
- Unity配置:已将.dll和.winmd文件复制到
Assets\Plugins\WSA\ARM路径,Platform Settings>CPU设为ARM;Player Settings中允许Unsafe Code,Api兼容性级别设为.NET Framework,构建平台为UWP,架构为ARM - 脚本智能感知无报错,Unity编译成功,仅运行时抛出异常,推测问题出在WinRT组件侧,询问可能的原因。
可能的原因及解决方向
- 组件未正确注册:UWP环境下WinRT组件需要完成注册才能被调用。Debug模式构建的组件可能未在测试设备/模拟器上完成注册,导致无法实例化类。可尝试先将组件部署到目标设备,再运行Unity项目;或改用Release模式构建组件(Release模式会自动处理部分注册逻辑)。
- 类工厂生成异常:虽然代码中定义了
factory_implementation下的RTClass,但C++/WinRT的代码生成可能出现问题,导致类工厂未正确导出。检查生成的RTClass.g.cpp文件,确认类工厂的注册代码是否存在;也可清理项目后重新构建组件,触发代码重新生成。 - ARM架构兼容性问题:Debug模式下的ARM构建可能存在未处理的架构相关问题,比如指针大小不匹配、原生指令兼容问题。可尝试切换到ARM64架构构建组件和Unity项目,或检查组件代码中是否有依赖特定架构的未兼容逻辑。
- 构造函数内部异常:RTClass构造函数中的实际代码(注释部分
// Do some stuff in the constructor)如果包含抛出异常的逻辑,可能导致实例化失败,WinRT异常在C#侧可能被包装为NullReferenceException。可暂时注释掉构造函数内的所有代码,测试是否能正常实例化。 - WinMD文件不完整或版本不匹配:复制到Unity的.winmd文件可能未正确包含RTClass的类型信息,或与.dll文件版本不一致。重新构建WinRT组件,确保复制最新生成的.winmd和.dll文件到Unity的Plugins目录。
内容的提问来源于stack exchange,提问作者nooway764
相关产品推荐
相关产品推荐

