4

JNA と DLL は私にとってまったく新しい領域です...次の宣言を持つ関数を持つカスタム DLL があります。

int myfunc (const char*);

dll は、次のコマンドを使用して MinGW で正常にコンパイルされます。

>gcc -shared -omydll.dll mydll.c -lgdi32

ただし、DLL 内で関数が見つからないため、JNA でのロードは失敗します。

public interface mydll extends StdCallLibrary {
  mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class);
  int myfunc (String arg);
  }

私はいくつかの調査を行いましたが、この特定のエラーは DLL 関数の呼び出し手順と関係があるようです。__stdcallと の__cdecl手順を見てきました。また、多くの DLL 関数__declspec(dllexport)が関数の宣言/実装の前に置かれていることもわかりました (これが何を意味するのか、何をするのかわかりません)。したがって、JNA の__stdcall方がプロシージャーを好むように思われるため、関数は次のようになります。

__declspec(dllexport) int __stdcall myfunc (const char*);

これは非常に複雑に見えますが、私が試した他のどの方法よりも優れているわけではありません. HashMap を使用してアンダースコア プレフィックスと @4 サフィックスを追加しても機能しませんでした。

mydll INSTANCE = (mydll)Native.loadLibrary("mydll", mydll.class, new HashMap () {{
  add("myfunc", "_myfunc@4");
  }});

JNAのドキュメントはまったく役に立ちませんでした。正直なところ、私はもう何をしているのかわかりません。

4

2 に答える 2

2

私は自分の DLL を問題なくビルドしていたことが判明し、JNA も自分の DLL を問題なく見つけていました。コンパイラがシンボルをどのように壊したかを判断する際にエラーが発生しました。私が好きな名前を付けた関数は、引数として取ったバイト数に応じてmyfuncエクスポートされました。JNAプロジェクトで使用したコードは次のとおりです。myfunc@8myfunc@32

import java.util.*;
import com.sun.jna.*;
import com.sun.jna.win32.*;
//
public class Test
  {
  public interface mydll extends StdCallLibrary
    {
    mydll INSTANCE = Native.loadLibrary("mydll", mydll.class, new HashMap {{
      put("myfunc", "myfunc@8");
      //Other functions
      }});
    public int myfunc (long arg);
    //Other functions
    }
  //
  public static void main (String[] args)
    {
    System.out.println
      (mydll.INSTANCE.myfunc((long)0x23A3920F)); //Or whatever
    return 0;
    }
  }

私のCコード:

#include <windows.h>
#include <stdio.h>

__declspec(dllexport) int __stdcall myfunc (__int64);
/* Other functions */

__declspec(dllexport) int __stdcall myfunc (__int64 arg)
  {
  /* Whatever */
  return return_value;
  }

GCC は-shared、最初の質問のように、スイッチと適切なライブラリへのリンクだけで満足していました。 関数名を正確に把握できるように、このツールをダウンロードすることを強くお勧めします。

于 2012-04-26T04:55:55.287 に答える
1

JNA 内のテスト ライブラリがどのように構築されているかを見てください (ネイティブ/Makefile)。その例に従うと、適切なエクスポート署名と呼び出し規約が示されます。

__declspec(dllexport)関数名をエクスポートする必要があることを示します。

__stdcallほとんどの MS API で使用されているものです。名前のマングリングでリンクが複雑になるだけなので、通常は自分のコードで使用する理由はありません。

実際にコンパイル (およびリンク) するときは、共有ライブラリを構築していることを GCC に伝える必要があります。ファイルに「*.dll」という名前を付けるだけでは十分ではありません。

gcc -o mydll.dll -shared mydll.c 

-l<libname>アクセスしているネイティブ ライブラリに応じて、最後に1 つ以上のオプションが必要になる場合があります。

于 2012-04-24T18:47:52.987 に答える