2011-01-21 18 views
1

これはヘッダーファイルの内容です。エラーの取得 "保護されたメモリの読み取りまたは書き込みを試みました"

/// 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); 

私は間違っていますか?

+0

これを確認しましたか? http://stackoverflow.com/questions/4402280/trouble-with-cc-dllimport-attempted-to-read-or-write-protected-memory –

+1

これは何らかの形で関係しているかもしれません。あなたはアットマークを"c:\ temp \ testGDB.gdb"となるので、 "\ t" -sはタブにならないかもしれません...おそらくあなたが得ているエラーはライブラリのバグです。 –

+0

@記号が機能しませんでした –

答えて

1

私は2つの可能性のある問題を参照してください。

C++コードはワイド文字列、C#のコードC++のコードが std::wstringクラスを使用している、としませ交流スタイルのヌル終了文字列を
  • ANSI文字列を使用している
    は、私はあなたがC++側のAPIを変更せずに第二の問題を簡単に解決することができるとは思わない

    は多分これは便利 です

  • +0

    はい、Pinvokeはstd:wstring(またはstd:文字列)にマーシャリングできません。 WCHAR *を使用するためにC++関数を変更するか、C++/CLRブリッジロジックを作成する必要があります。 – shf301

    +0

    C++/CLRブリッジロジックはどのように見えますか? :-) –

    +0

    私はC + +の文字列のブリッジを行ういくつかのコードがありますが、それを動作させる方法を知らない。私はC++/CLRプロジェクトを作成してコンパイルしましたが、何らかの理由でその関数が利用できません。公開するにはいくつかの方法を試しましたが、間違いが続いていました。 http://www.nuclex.org/articles/5-cxx/10-marshaling-strings-in-cxx-cli –

    0

    .NET 4.0を使用している場合は、refキーワードなしでパラメータを渡してみてください。

    すなわち

    FileGDBAPI_wrapper.CreateGeodatabase( "C:\ TEMP \ testGDB.gdb"、/ REF /ジオデータベース)

    この場合、私にお知らせください。

    EDIT

    は、私は一般的に無知だった、私の前の回答を忘れます。

    Geodatabaseを、refの代わりにoutとマークする必要があると思います。これは、関数の宣言と呼び出しの両方でです。問題がないように参照としてライブラリに格納されたジオデータベースの引数を宣言に関連する - この場合には、あなたは私は - そして、私はまだ無知だことも推測CreateGeodatabase()

    に渡す前に、あなたのIntPtrを初期化する必要はありませますつまり、null(IntPtr.Zero)を渡すことはできません。通常、必要がないので、outパラメータとして必要です。

    +0

    C#引数は構造体であるIntPtrなので、参照渡しでないとネイティブ関数によって変更することができます。参照型の場合は正しいでしょう。 .NET 4に何かがないと、このことが実際にどのように変化するかはわかりませんが、あなたの答えがどのように働くかわかりません。 –

    +0

    私はrefを使用しないようにしようとしましたが、同じエラーです。 –

    +0

    ネイティブ関数の定義を教えてください。 –

    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)); 
         } 
    
    関連する問題