none
アンマネージdllからレジストリの値が取得できない RRS feed

  • 質問

  • お世話になります。

     

    既存システムにてアンマネージで作成されたレジストリの値を読み込むhoge.dllがあります。 現在はC#にて開発を行っているので、hoge.dll のメソッドをコールして、レジストリの値を取得しようとしているのですが、うまく取得できません。

    hoge.dllは動作実績もあり、アンマネージのテストプロを作成しhoge.dllをコールすると値が取得できるので、マネージプログラムからの呼び出しで何か制限があるのかと思っていますがそれらしい情報が見つかりませんでした。

    どなたか、ご存知の方がいましたら教えていただきたいのですが・・・

     

    以下、開発環境&ソースの抜粋です。

    WinXP,.NET Framework2.0

     

    Code Snippet

    public class ABC

    {

      [DllInport("hoge.dll")]

      private static extern int GetRegValUnmanage(StringBuilder outVal, int outSize);

     

      public void CallRegVal()

      {

        StringBuilder outVal = new StringBuilder(128);

        int len = GetregValUnmanage(outVal, outVal.Length);

        // ↑ lenは0、outValにも何も入っていません

      }

     

    2007年4月24日 7:04

回答

  • 蒼の洞窟さんのおっしゃるとおりでMSDNで調べてみたら

    >既定の呼び出し規約は StdCall です。

    と書かれていました。

    どうも失礼しました。

    他にこのスレッドを見た人に間違えた情報を伝えることになるので、修正しました。

    2007年4月25日 8:14

すべての返信

  • GetRegValUnmanageは結果をどのように格納するのでしょうか?
    文字コード等意識していますか?

    アンマネージドDLLがC/C++で作成されているのであればその関数のプロトタイプ宣言
    ぐらいは載せてもらわないと。。。
    2007年4月24日 7:15
  • 失礼しました。

    アンマネージ側は以下のようになっています。

     

    Code Snippet

    // hoge.h

    __declspec(dllexport) int GetRegValUnmanage(LPSTR lpOutVal, int nOutSize);

     

    // hoge.cpp

    __declspec(dllexport) int GetRegValUnmanage(LPSTR lpOutVal, int nOutSize)

    {

      char readVal[128];

     

      // readValにレジストリから値を読み込む

      strcpy(lpOutVal, readVal);   // レジストリから読み込んだ値をコピー

      strcat(lpOutVal, "abc");     // 文字列"abc"を連結

     

      return strlen(lpOutVal);

    }

     

    マネージ側から呼び出すと、上記のreadValが何も取得できずに、strcatした”abc”だけが返ってきます。

     

    2007年4月25日 5:12
  • readValにレジストリから値を読み込む

    の処理はどこでしょうか?
    その処理がうまくいっているのは確認できているのでしょうか?
    (DLL側でMessageBoxで表示してみたりして)


    呼び出し規約はDLL側で設定していないのでしょうかね?(WINAPIとか__stdcallとか)
    デフォルトだと、__cdeclになるんだっけかな?

    [DllInport("hoge.dll")]
    private static extern int GetRegValUnmanage(StringBuilder outVal, int outSize);


    Code Snippet
    [DllImport("hoge.dll",
               CharSet=CharSet.Ansi,
               CallingConvention=CallingConvention.Cdecl)]
    private static extern int GetRegValUnmanage(StringBuilder outVal,
                                                int outSize);

     


    としたらどうなりますか?
    2007年4月25日 5:25
  • 呼び出されたDLLが正常に動作していないということから、
    呼び出し規約が一致していない可能性がありそうですね。
    CallingConventionを指定しなかった場合はCallingConvention.StdCallになりますが、
    VC++でのデフォルトは__cdeclですからDLL側は__cdeclで、C#側でのCallingConventionにCallingConvention.Cdeclを指定する必要があるもしれないです。

    ソースとヘッダーの関数宣言に呼び出し規約が書かれていない場合は、
    DLLのプロジェクトの呼び出し規約の設定になりますので、念のためそちらも確認してみてください。

    2007年4月25日 6:13
  • CallingConventionを指定しなかった場合はCallingConvention.Cdeclになるので、


    DllImportAttribute.CallingConvention フィールド 
    http://msdn2.microsoft.com/ja-jp/library/system.runtime.interopservices.dllimportattribute.callingconvention(VS.80).aspx
    より
    CallingConvention フィールドの既定値は Winapi です。

    とあり、
    CallingConvention 列挙体 
    http://msdn2.microsoft.com/ja-jp/library/system.runtime.interopservices.callingconvention.winapi(VS.80).aspx
    より
    Winapi

    このメンバは実際には呼び出し規約ではありません。代わりに、既定のプラットフォーム呼び出し規約を使用します。たとえば、Windows では StdCall、Windows CE .NET では Cdecl が既定値になります。 

    とあるのですが、Cdeclになるのでしょうか?
    そうすると、WinAPIを使うときには毎回CallingConvention=CallConvention.StdCallが必要になるわけなんですよね?



    追記

    __stdcall をDLLにつける場合、現在DEFファイルをつかっていないのであれば、使用するか、
    C#側でDllImportでEntryPointを指定するか、序数指定にするかどちらかになるでしょう。
    2007年4月25日 6:25
  • 蒼の洞窟 さん、勝良三柴 さん 大変申し訳ありませんでした 

    デバッグ環境に不備があり、違うDllを呼んでいました・・・

     

    よく確認もせず、質問をしてしまいお手間をとらせてしまったことをお詫びいたします。

    次回からは、もっと自分を疑ってから質問するようにしますので、これに懲りずに

    また、よろしくお願いいたします。

     

    # アンマネージを使用する場合は呼び出し規約に注意しなければならないこと、

    # 大変勉強になりました、ありがとうございました。

     

    2007年4月25日 7:47
  • 蒼の洞窟さんのおっしゃるとおりでMSDNで調べてみたら

    >既定の呼び出し規約は StdCall です。

    と書かれていました。

    どうも失礼しました。

    他にこのスレッドを見た人に間違えた情報を伝えることになるので、修正しました。

    2007年4月25日 8:14