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

调用Marshal.StructureToPtr时抛出“类型库未注册”异常求助

异常解决方法:Typelib export: Type library is not registered (0x80131165)

问题根源

该异常是因为直接用Marshal.SizeOf和Marshal.StructureToPtr处理包含托管数组和未明确序列化规则的字符串的结构体时,.NET无法自动完成托管到非托管内存的转换,触发类型库导出失败(这类复杂嵌套的引用类型结构体无法通过默认类型库机制处理)。此外原结构体存在字段拼写错误,会导致参数长度赋值无效,加剧问题。


具体修复步骤

1. 修正结构体定义,添加非托管序列化规则

修改结构体为非托管兼容形式:用IntPtr替代托管数组,给字符串字段明确指定非托管类型:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct PLUGIN_PARAMETER_DATA
{
    // 指定字符串转换为Unicode非托管字符串
    [MarshalAs(UnmanagedType.LPWStr)]
    public string version;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string name;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string data;
}

[StructLayout(LayoutKind.Sequential)]
public struct PLUGIN_DATA
{
    // 修正原拼写错误(paramter → parameter)
    public int parameterDataLength;
    // 用IntPtr指向非托管内存中的参数数组
    public IntPtr pluginParameterData;
}

2. 手动分配非托管内存并复制数据

不能直接依赖Marshal自动处理数组,需要手动分配数组内存并逐个复制结构体:

// 初始化参数数组(修正JSON字符串的引号转义)
var paramList = new[]
{
    new PLUGIN_PARAMETER_DATA 
    { 
        Name = "StartingPlugin", 
        Version = "1", 
        Data = "BD9B5012-4B81-4DBA-876E-DD6829208F3A" 
    },
    new PLUGIN_PARAMETER_DATA 
    { 
        Name = "StartingPluginParameter", 
        Version = "1", 
        Data = "{ \"parameterModelVersion\":1,\"parameterModelJson\":\"{\\\"parameterData\\\":{\\\"star-rating\\\":5}}\"}" 
    },
    new PLUGIN_PARAMETER_DATA 
    { 
        Name = "StartingPluginPriority", 
        Version = "1", 
        Data = "1" 
    }
};

// 构建PLUGIN_DATA对象
PLUGIN_DATA pluginData = new PLUGIN_DATA();
pluginData.parameterDataLength = paramList.Length;

// 分配参数数组的非托管内存:单个参数大小 × 参数数量
int singleParamSize = Marshal.SizeOf(typeof(PLUGIN_PARAMETER_DATA));
pluginData.pluginParameterData = Marshal.AllocHGlobal(singleParamSize * paramList.Length);

// 逐个复制参数到非托管内存
IntPtr currentParamPtr = pluginData.pluginParameterData;
foreach (var param in paramList)
{
    Marshal.StructureToPtr(param, currentParamPtr, false);
    currentParamPtr = IntPtr.Add(currentParamPtr, singleParamSize);
}

// 分配PLUGIN_DATA的非托管内存并复制
int pluginDataSize = Marshal.SizeOf(typeof(PLUGIN_DATA));
IntPtr pluginDataBuff = Marshal.AllocHGlobal(pluginDataSize);
Marshal.StructureToPtr(pluginData, pluginDataBuff, false);

3. 完善内存释放逻辑,避免泄漏

在finally块中释放所有分配的非托管内存,注意先释放数组内的字符串资源,再释放数组和结构体内存:

finally
{
    // 释放参数数组的内存
    if (pluginData.pluginParameterData != IntPtr.Zero)
    {
        int singleParamSize = Marshal.SizeOf(typeof(PLUGIN_PARAMETER_DATA));
        IntPtr currentParamPtr = pluginData.pluginParameterData;
        for (int i = 0; i < pluginData.parameterDataLength; i++)
        {
            // 销毁结构体中的字符串非托管资源
            Marshal.DestroyStructure(currentParamPtr, typeof(PLUGIN_PARAMETER_DATA));
            currentParamPtr = IntPtr.Add(currentParamPtr, singleParamSize);
        }
        Marshal.FreeHGlobal(pluginData.pluginParameterData);
    }

    // 释放PLUGIN_DATA的内存
    if (pluginDataBuff != IntPtr.Zero)
    {
        Marshal.FreeHGlobal(pluginDataBuff);
    }

    // 若有COPYDATASTRUCT的内存也需同步释放
    if (copyDataBuff != IntPtr.Zero)
    {
        Marshal.FreeHGlobal(copyDataBuff);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:39:23