将byte []或内存流传递给外部非托管方法时发生AccessViolationException

时间:2014-05-01 20:31:29

标签: c# stream slimdx direct3d9

我在托管Windows应用程序(Win.XP,.Net 3.5)中使用SlimDX。 SlimDX处理所有非托管DirectX API调用。我试图调用SlimDX框架中的以下方法:SlimDX.Direct3D9.XFile.CreateEnumerationObject(Stream stream)。这是实施:

XFile xfile = new XFile();
XFileEnumerationObject enumObj = null;
string Filename = @"MyDocs\Test.x";
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read))
{
    enumObj = xfile.CreateEnumerationObject(fs);
}

当我调用此方法时,我得到以下异常:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at SlimDX.Direct3D9.XFile.CreateEnumerationObject(Byte[] memory)
   at SlimDX.Direct3D9.XFile.CreateEnumerationObject(Stream stream)
   at SceneGenerator.ContentManager.XParser.Parse(XParserMode Mode, MeshFlags options, List`1& materialPartitions, GDEAssetConfig& cfg, _XData& userContext, Byte[] filedata) in D:\Documents and Settings\GDEAuxiliary\My Documents\Visual Studio 2010\Projects\SceneGenerator\SceneGenerator\XParser.cs:line 191

SlimDX用于处理此内存流到字节数组的转换,以及字节数组到非托管内存的转换。我想文件数据没有加载到预期的文本编码中......

我已经使用SlimDX框架中的替代方法验证了该文件,该方法使用文件名和指定的字符集创建枚举对象...这里是实现:

XFile xfile = new XFile();
XFileEnumerationObject enumObj = null;
string Filename = @"MyDocs\Test.x";
enumObj = xfile.CreateEnumerationObject(cfg.Filename, System.Runtime.InteropServices.CharSet.Auto);

这种方法很好......

我可以做些什么来为SlimDX准备内存流...遗憾的是,我并不完全确定SlimDX对内存流的期望是什么......

1 个答案:

答案 0 :(得分:1)

我去过那里。我不得不使用c#应用程序中的HBA API。无论我做了什么,传递一个字节数组都给了我类似的错误。

对我有用的解决方案是将Byte []数组封装在一个stuct中,然后使用该结构。确保结构中的字节数组定义为Marshal.ByValArray,以便c#知道其大小和所有内容。

根据我的经验,经验法则是将事物传递给非托管内存时确保已为其分配了托管内存。

此外,我确信您已经检查了,但请确保您的FileStream对象有效,它可以访问文件,文件不为空。

以下是结构的示例:

    /*
    typedef struct HBA_wwn {
    HBA_UINT8 wwn[8];
    } HBA_WWN, *PHBA_WWN;
    */
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct HBA_WWN
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public Byte[] wwn;

        public static HBA_WWN getInstance()
        {
            HBA_WWN wwn = new HBA_WWN();
            wwn.wwn = new Byte[8];

            return wwn;
        }
    }