JNA を使用して Java コードを DLL にマッピングする場合、C の関数引数がポインタの場合、C 呼び出しでJava 配列 ( int[]
、 )をどのように渡す/使用する必要がありますか? double[]
私はバグに直面しています.Cへの配列のマッピングのどこかにあると思います.
私が試したこと:そして私が修正しようとしているバグ
私のプロジェクトでは、clp-javaの背後にあるコードベースを再構築する必要があります。そうすることで、LP 問題の制約を追加する次の関数を含む C ヘッダー ファイルがあります (例: 2.25*x1 - 3.3*x2 =4
)。
CLPLIB_EXPORT void CLP_LINKAGE Clp_addRows(Clp_Simplex *model, int number,
const double *rowLower, const double *rowUpper,
const CoinBigIndex *rowStarts, const int *columns,
const double *elements);
Java では、、、、rowLower
およびrowUpper
JavarowStarts
配列(のいずれか) がありcolumnscolumns
ます。clp -javaは BridJ を使用し、上記の関数は経由で呼び出されますelements
int[]
double[]
CLPNative.clpAddRows(pointerToModel, number,
Pointer.pointerToDoubles(rowLower),
Pointer.pointerToDoubles(rowUpper),
Pointer.pointerToInts(rowStarts),
Pointer.pointerToInts(columnscolumns),
Pointer.pointerToDoubles(elements));
プレーンな JNA を使用すると、JNA のドキュメントには、C 関数の呼び出しが次のようになるように、配列がポインターにマップされると記載されています。
CLPNative.clpAddRows(pointerToModel, number,
rowLower, rowUpper, rowStarts, columnscolumns, elements);
残念ながら、両方のメソッドに同じ配列を渡してメモリ内のデータを取得すると、制約の2 番目の変数に対して異なる答えが得られます (最初の変数は問題ありません)。BridJ は -3.3 を生成し、私の JNA メソッドは 1.777E-307 を出力します。同じ DLL、同じマシン (Java 11)。
インターネットでこの例を見つけました。これは、Java の配列を JNA ポインターにマップし、このポインターを C 関数に渡します。これを使ってみました:
private Pointer intArrayToPointer(int[] pArray) {
Pointer pointerToArray = new Memory(pArray.length*Native.getNativeSize(Integer.TYPE));
for (int i=0; i< pArray.length; i++) {
pointerToArray.setInt(i, pArray[i]);
}
return pointerToArray;
}
JNA関数呼び出しでこれを使用すると(そしてそれに応じてJNAインターフェースを変更すると)、「無効なメモリアクセス」というJavaエラーが発生します。この StackOverflow Q/Aに基づいてこれを修正します(のオフセットsetInt()
を でシフトする必要がありますNative.getNativeSize(Integer.TYPE)
。同じ誤った出力が明らかになります (x2 の係数は -3.3 ではなく 1.777E-307 です)。
CLPNative.clpAddRows(pointerToModel, number,
doubleArrayToPointer(rowLower),....);
追加情報:次の関数/メソッドで係数を確認します。
public double getNativeConstraintCoefficient(CLPConstraint pConstraint, CLPVariable pVariable) {
<... some magic to compute the position...>
Pounter<Double> elements = CLPNative.Clp_GetElements(pointerToModel);
return elements.getDoubleAtIndex(pos-1); // using BridJ
return elements.getDouble(pos - 1) // using JNA
}