You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过mono_assembly_load_from返回的IntPtr获取System.Reflection.Assembly

如何通过Mono返回的IntPtr获取System.Reflection.Assembly对象?

我通过Mono原生方法将程序集加载到应用中,目前只能得到IntPtr类型的返回值,但实际需要获取System.Reflection.Assembly类型对象。请问怎么通过这个IntPtr得到对应的Assembly实例?

我当前导入并使用的Mono方法如下:

public static class MonoCalls {
    [DllImport("__Internal", EntryPoint = "mono_image_open_from_data")]
    public static extern IntPtr MonoImageOpenFromData(IntPtr dataHandle, int dataLenght, bool shouldCopy, IntPtr status);

    [DllImport("__Internal", EntryPoint = "mono_assembly_load_from")]
    public static extern IntPtr MonoAssemblyLoadFrom(IntPtr imageHandle, string name, IntPtr status);
}

用于加载程序集到内存的类(输入为程序集字节数组):

public class Mono {
    IntPtr Image;
    IntPtr Assembly;
    public IntPtr Activate(byte[] Bytes) {
        unsafe {
            fixed (byte* Pointer = Bytes) {
                Image = MonoCalls.MonoImageOpenFromData((IntPtr)Pointer, Bytes.Length, true, IntPtr.Zero);
                Assembly = MonoCalls.MonoAssemblyLoadFrom(Image, string.Empty, IntPtr.Zero);
                return Assembly;
            }
        }
    }
}

主代码逻辑:

...

Mono Mono = new();
byte[] Assembly_Bytes = ...; // 程序集字节数组
IntPtr Pointer = Mono.Activate(Assembly_Bytes);
string MyAssemblyName = "MyAssembly";

Assembly FoundAssembly;
foreach (Assembly Assembly in AppDomain.CurrentDomain.GetAssemblies()) {
    if (Assembly.GetName().Name.Equals(MyAssemblyName)) {
        FoundAssembly = Assembly; // 找到同名程序集(可能存在重名风险)
        return;
    }
}

Type[] Types = FoundAssembly.GetTypes(); // 最终目的是获取程序集中的类型
...

是否存在类似GetAssemblyByPtr(IntPtr)的方法可以直接返回System.Reflection.Assembly?

注:简单的Assembly.Load()不适用于我的场景。


解决方案:使用Mono的mono_assembly_get_object API

Mono原生提供了mono_assembly_get_object方法,可直接将程序集的IntPtr指针转换为托管的System.Reflection.Assembly对象。你需要先在MonoCalls类中添加该方法的导入:

public static class MonoCalls {
    // 已有的两个方法...

    [DllImport("__Internal", EntryPoint = "mono_assembly_get_object")]
    public static extern IntPtr MonoAssemblyGetObject(IntPtr appDomain, IntPtr assembly);
}

之后在代码中通过以下方式完成转换:

// 获取当前AppDomain的原生指针(默认域可传IntPtr.Zero,显式获取更稳妥)
IntPtr appDomainPtr = AppDomain.CurrentDomain.GetNativeHandle();
// 将原生程序集指针转换为托管Assembly对象
Assembly loadedAssembly = (Assembly)Marshal.PtrToStructure(MonoCalls.MonoAssemblyGetObject(appDomainPtr, Pointer), typeof(Assembly));

关键注意事项

  • 版本兼容性:该API行为随Mono版本可能略有变化,确保使用的Mono版本支持此方法(主流稳定版本均兼容)。
  • AppDomain匹配:必须保证传入的AppDomain指针与程序集加载的域一致,否则会引发异常或返回无效对象。
  • 内存安全:不要在程序集已被卸载后使用该指针,否则会导致内存访问错误。
  • 重名规避方案:如果直接转换出现问题,可结合mono_assembly_get_name精准定位程序集,避免同名冲突:
    // 额外导入获取程序集名称的API
    [DllImport("__Internal", EntryPoint = "mono_assembly_get_name")]
    public static extern IntPtr MonoAssemblyGetName(IntPtr assembly);
    
    // 获取原生程序集的名称字符串
    string assemblyName = Marshal.PtrToStringAnsi(MonoCalls.MonoAssemblyGetName(Pointer));
    // 精准匹配查找托管Assembly对象
    FoundAssembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == assemblyName);
    

内容的提问来源于stack exchange,提问作者Cat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:17:42