跨目录下mono_add_internal_call调用失败问题及替代方案咨询
跨进程C++调用Unity C#内部函数问题排查与解答
问题背景
我有一个C++项目(路径为/Project/Server/Main.cpp),希望调用Unity C#项目(路径为/Project/Client)DLL中的函数,按照Mono文档实现了如下代码:
C++代码
static MonoString* Sample() { return mono_string_new(mono_domain_get(), "Hello CPP"); } int main() { domain = mono_jit_init("MyGame"); MonoAssembly* assembly = mono_domain_assembly_open(domain, unity_main_dll_path); image = mono_assembly_get_image(assembly); mono_add_internal_call("Game.Call2Cpp::TestCall", Sample); return 0; }
Unity C#代码
namespace Game { public class Call2Cpp : MonoBehaviour { [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern void TestCall(); void Update() { if(Input.GetKeyDown(KeyCode.T)) { TestCall(); } } } }
错误信息
按下T键触发调用时出现以下错误:
MissingMethodException: assembly:<unknown assembly> type:<unknown type> member:(null) Game.Call2Cpp.Update () (at Assets/Scripts/Game/Multiplayer/Call2Cpp.cs:26)
因两个项目分属不同目录无法合并,有以下疑问:
- 是否是目录不同导致的问题?跨目录下如何正确使用
mono_add_internal_call? - 跨目录场景下,C++通过Mono调用C#是否有其他替代方案?
- 我的
mono_add_internal_call用法是否存在错误?查询发现他人类似用法可正常运行。 - 移除
Call2Cpp的MonoBehaviour特性,通过其他脚本调用仍出现相同错误,原因何在?
解答
1. 目录不同不是直接原因
mono_add_internal_call只关心程序集的加载路径和函数签名匹配,跟项目目录无关。你需要注意:
- 确保
unity_main_dll_path指向Unity编译后生成的正确DLL(比如Assembly-CSharp.dll,通常在Client/Build/[平台名]_Data/Managed目录下) - 加载程序集后,建议用
mono_class_from_name(image, "Game", "Call2Cpp")验证是否能找到目标类,确认加载的是正确的程序集
2. 跨目录/跨进程的替代方案
如果是两个独立进程(C++服务端和Unity客户端),推荐这些方案:
- 进程间通信(IPC):用命名管道、Socket、共享内存等方式直接通信,不需要依赖Mono内部机制,兼容性更强
- Unity原生插件:把C代码编译成Unity支持的插件(Windows下为
.dll,Mac下为.bundle),C#用[DllImport]调用C函数;C++可以通过Unity提供的SendMessage/Invoke接口或者回调函数调用C#方法 - 跨语言通信框架:比如gRPC、ZeroMQ这类成熟框架,适合复杂的跨进程调用场景,自带序列化和通信机制
3. mono_add_internal_call的用法错误
你的代码有两个核心问题:
- 函数签名完全不匹配:C++的
Sample返回MonoString*,但C#的TestCall声明为void类型,Mono无法匹配到对应实现,必然报缺失方法 - 注册时机和域错误:你在独立的C进程中初始化了自己的Mono域并注册调用,但Unity是另一个独立进程,有自己的Mono域,你的注册对Unity完全无效。正确做法是把C代码编译成Unity插件,让Unity在启动时加载并执行注册逻辑,而不是单独跑C++进程
4. 移除MonoBehaviour无效的原因
核心问题跟是否继承MonoBehaviour无关,而是:
- 函数签名不匹配的问题没解决
- C++的注册逻辑根本没在Unity的Mono域中执行,Unity完全不知道你注册了这个内部调用
- 两个进程的Mono域相互独立,独立C++进程的注册无法作用于Unity进程
内容的提问来源于stack exchange,提问作者LoneliNerd
相关产品推荐
相关产品推荐

