获取错误“尝试读取或写入受保护的内存”

时间:2011-01-21 21:25:10

标签: c# c++ dllimport

这是头文件中的内容。

/// Creates a new file geodatabase in the specified location.
/// @param[in]    path The location where the geodatabase should be created.
/// @param[out]   geodatabase A reference to the newly-created geodatabase.
/// @return       A long integer indicating whether the method finished successfully.
EXT_FILEGDB_API long CreateGeodatabase(const std::wstring& path, Geodatabase& geodatabase);

这就是我的dllimport的样子。

[DllImport("FileGDBAPI.dll", EntryPoint = "#49", SetLastError=true, CallingConvention=CallingConvention.Winapi)]
        public static extern int CreateGeodatabase([MarshalAs(UnmanagedType.LPStr)]string path, ref IntPtr geodatabase);

..这是使用它的代码。

IntPtr Geodatabase = IntPtr.Zero;
                FileGDBAPI_wrapper.CreateGeodatabase("c:\temp\testGDB.gdb", ref Geodatabase);

我做错了什么?

3 个答案:

答案 0 :(得分:1)

我看到两个可能的问题:

  1. C ++代码使用宽字符串,C#代码为ANSI字符串
  2. C ++代码使用std::wstring类,而不是c样式的空终止字符串
  3. 我认为如果不改变C ++方面的API,你不能轻易解决第二个问题

答案 1 :(得分:0)

如果您使用的是.NET 4.0,请尝试传递不带ref关键字的参数。

<德尔>即

FileGDBAPI_wrapper.CreateGeodatabase(“c:\ temp \ testGDB.gdb”,/ ref / Geodatabase);

并告诉我这是否适合您。

修改

忘记我之前的回答,我通常是无知的。

我认为您需要在函数的声明和调用中将Geodatabase标记为out而不是ref;在这种情况下,您 NOT 需要初始化您的IntPtr,然后再将其传递给CreateGeodatabase()

我猜 - 可能是我仍然无知 - 问题与将库中的Geodatabase参数声明为引用而不是指针有关,也就是说,您无法将null(IntPtr.Zero)传递给它,通常,你不需要它,你需要它作为out参数。

答案 2 :(得分:0)

也许这很有用

void MarshalString ( String ^ s, wstring& os ) {
            using namespace Runtime::InteropServices;
            const wchar_t* chars = 
                (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();
            os = chars;
            Marshal::FreeHGlobal(IntPtr((void*)chars));
        }