0

.NET Compact Framework のデバッグに関する最近の質問の補足として、私は現在、.NET Compact Framework と .NET Framework アプリケーションの両方から OpenGL ES を使用しようとしています。OpenGL ES 用に作成され、libGLES_CM.dll からインポートされるこのラッパーを使用します。

デバッグを容易にするために、.NET Framework アプリケーションを作成し、OpenGL ES と EGL のインポート プロジェクトを同じファイル (デスクトップ フレームワーク用にビルドしただけ) で再作成し、DLL 名の定数を作成して、libGLESv2.dll からインポートするようにしました。 Windows では libEGL.dll、CF では libGLES_CM.dll から。DLL は PowerVR OpenGL ES エミュレーション SDK (ターゲット デバイスには PowerVR SGX があります) からのものであり、実際の OpenGL 実装の単なる OpenGL ES ラッパーです。そして、ここに問題があります:

ラッパー ライブラリでは、OpenGL 関数は 2 つの静的クラス (gl と egl) にあり、通常の名前を持ちますが、gl/egl プレフィックスがないためegl.GetDisplay()egl.eglGetDisplay(). それらは次のようにインポートされます。

[DllImport(DllName, EntryPoint = "eglGetDisplay")]
static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);

これは、Compact Framework で問題なく動作します。デスクトッププロジェクトでは、 EntryPointNotFoundException がスローされます-関数の名前が次のようになっているためです_eglGetDisplay@4 (補足:WMDはブロッククォートのAlt-Gr + Qをキャッチします。これはドイツ語のキーボードレイアウトのアットマークです。これを貼り付ける必要がありました。)ディペンデンシー ウォーカーへ。

条件付きで文字列定数を空の文字列または「_」に設定し、それとエントリポイント名を連結することにより、デスクトッププロジェクトの関数名にアンダースコアを追加できましたが、CF のものには追加できませんでした。これ:

[DllImport(DllName, EntryPoint = FunctionPrefix + "eglGetDisplay")]

ここでは問題ありません。しかし、@4 (正確には何ですか?) がないため、関数はまだ見つかりません。@4 を追加するとうまくいきますが、ここではすべての関数の値が異なるため、これを手動で行う必要があり、CF バージョンでは数値が正しくない可能性があります。ここに奇妙な部分があります:

エントリ ポイントを指定せず、代わりに関数に名前を付ける必要がある場合、インポートは正常に機能します。これは二重の接頭辞 (静的クラス名と関数名) のために醜いですが、これにラッパーを追加するだけでこれを回避できます。私はこれらの関数に大きく依存しないので (かなり単純な 2D エンジンのみが必要です)、これは問題にはなりませんが、正しくないと感じます。

エントリ ポイントを指定すると機能しないのはなぜですか? 本来のように機能させるにはどうすればよいですか?

4

3 に答える 3

4

CF とデスクトップ API のエントリ ポイントが異なる場合は、これを使用する必要があります。これは、異なる DllImport を定義する必要があることを意味します。

最も簡単なのは、すべての内部 (.NET) 名を実装する 2 つのラッパー クラスを用意し、それらのインポートを呼び出して、プラットフォームに応じて実行時に正しいものをインスタンス化することです。次に、共通インターフェースを介して API にアクセスします。

Interface IGLImports {
   IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

static class CFRawImports {
  [DllImport(DllName, EntryPoint = "eglGetDisplay")]
  static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

static class DeskRawImports {
  [DllImport(DllName, EntryPoint = "_eglGetDisplay@4")]
  static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

class DesktopImports : IGLImports {
  public IntPtr GetDisplay(EGLNativeDisplayType display_id) {
    return DeskRawImports.GetDisplay(display_id);
  }
}

class CFImports : IGLImports {
  public IntPtr GetDisplay(EGLNativeDisplayType display_id) {
    return CFRawImports.GetDisplay(display_id);
  }
}

static class ImportLoader {
  public static IGLImports GetImports() {
    if (isCF) {
      return new CFImports();
    } else {
      return new DesktopImports();
    }
  }
}

class MyApp {
  private static IGLIMports gl = ImportLoader.GetImports();

  // In code use gl.GetDesktop(...)

編集: インターフェイスと 4 つのクラスは、少しのコード生成で作成できるはずです。Name DesktopImport CFImport を含む入力ファイル (これらが異なる場合は、dll 名を追加する可能性があります)。VS の T4 テンプレートを学ぶ言い訳になるでしょう...

于 2009-03-17T13:06:24.137 に答える
1

修飾名は、関数定義またはプロトタイプのコンパイル中にコンパイラによって作成される文字列です。名前の「@4」は、パラメーターの合計長が 4 バイト (32 ビット整数?) であることを意味します。

dumpbin.exeを使用して、装飾された名前を .dll から取得できます。

于 2009-03-17T13:05:07.523 に答える
0

#define yourdllname_API extern "C" __declspec(dllexport)を使用して、dll内のメソッドを公開し、上記の例外を取得しないように関数の装飾を回避します。例:

DLL:

#ifdef DEPLOYHOOK_EXPORTS
#define DEPLOYHOOK_API  extern "C" __declspec(dllexport)
#else
#define DEPLOYHOOK_API  __declspec(dllimport)
#endif

// This class is exported from the DeployHook.dll

DEPLOYHOOK_API int nDeployHook;


DEPLOYHOOK_API bool InstallHook(void);
DEPLOYHOOK_API bool UnInstallHook(void);

Project / exeの呼び出し:

[DllImport("DeployHook.dll",EntryPoint = "InstallHook",CharSet = CharSet::Auto, SetLastError = true)]   extern bool InstallHook(void);

//EntryPointNotFoundExceptionは回避されました

于 2009-07-17T05:37:34.353 に答える