JNIについて

[戻る]
TADA 2004/08/07(土) 07:50:04
開発環境はVC++.NET,JBuilderです。
VC++で作成したDLLがございます。
DLLの中に変数郡(構造体)があり
JBuilderで作成した画面がスレッドで定期的に変数を読みに行き
LEDを点灯させたいと考えております。

まず、それは可能でしょうか?

javaから構造体を丸々コピーすることはできないですか?(構造体のメンバアドレスによ
りますが…。)
もしだめなら構造体に対して、構造体のメンバをひとつひとつ見るしかないのでしょう
か?

PAI 2004/08/10(火) 10:30:50
> DLLの中に変数郡(構造体)があり
> JBuilderで作成した画面がスレッドで定期的に変数を読みに行き
> LEDを点灯させたいと考えております。
> 
> まず、それは可能でしょうか?


> LEDを点灯
というのが良くわかりませんが、

DLL内のオブジェクトを定期的にJNIから見に行くこと自体は
(少々面倒ではありますが)可能です。


> javaから構造体を丸々コピーすることはできないですか?
> (構造体のメンバアドレスによりますが…。)

できないんじゃないでしょうか?よくわかりませんが。

TADA 2004/08/12(木) 09:17:00
> javaから構造体を丸々コピーすることはできないですか?
> (構造体のメンバアドレスによりますが…。)
はDLLの構造体のメンバをひとつひとつ読みに行き
保存する形になるのですね。

>DLL内のオブジェクトを定期的にJNIから見に行くこと自体は
>(少々面倒ではありますが)可能です。
参考サイトご存知でしょうか?
DLLではなくてかまいません。C言語で書かれた構造体の変数取得方法が記述された
ところがあればお願いいたします。

PAI 2004/08/12(木) 15:19:32
> > javaから構造体を丸々コピーすることはできないですか?
> > (構造体のメンバアドレスによりますが…。)
> はDLLの構造体のメンバをひとつひとつ読みに行き
> 保存する形になるのですね。

丸々コピーするのが無理、といっただけで、
別にJavaのほうでそれ用のクラスを作って、
そのインスタンスを DLL に渡して、
DLLの方で値をそれぞれぶち込んでやっても構いませんけれど?

>C言語で書かれた構造体の変数取得方法
についての、そのものズバリの参考サイトはなかなかないと思いますよ。

面倒くさいだけで、何も特別なことはないわけだし、
JNI と DLL それぞれ調べて、それを組み合わせれば、
おのずと道は見えてくると思いますが・・・

どちらかというと、値の取得方法よりも、
その構造体自体の生成と寿命の管理の問題のほうが重要だと思いますけれど。

Bosscat 2004/08/12(木) 22:15:18
TADAさんはどこまで出来たのでしょうか?
JNIまで辿り着いているのだから、もう、ほとんど出来たと同じはずですが・・・

本家のチュートリアル
http://java.sun.com/docs/books/tutorial/native1.1/implementing/field.html
JavaオブジェクトにC側がアクセスする方法です。

構造体を丸ごとコピーという話は結論から言うと不可能です。

これは、プラットホーム依存である、C構造体のメモリマップと、
Javaのバーチャルマシーン上のメモリーマップが等しい保障がないからです。
(だからGetCharArrayElements()等の関数が必要になるのです。)
ですから、JNIに忠実に従うのが正解です。

下のようにすれば、一応、データのシリアライズ(平坦化)によって受け渡しも可能です。

例によってコンパイル等の検証を行っていないので、間違ってたら指摘してください。
********* java 側 ***************
public class JClassHoge{
 private static native void CFunc(char[] charar);
 static { System.loadLibrary("hogehoge"); } 
 public static void main (String[] args){ 
  char buf[]=new char[9];
  CFunc(buf);
   :
  こんな感じのマッピング
  buf[0] -> Foo::a

  buf[1] -> Foo::i[0] -- (c[0])
   :
  buf[4] -> Foo::i[0] -- (c[3])
   :
  buf[8] -> Foo::i[1] -- (c[7])
 }
};

********* C 側 ***************
--- VC++ ---
#pragma pack(push,1)
struct Foo{
 char a;
 union{
  int  i[2];
  char c[8];
 }
};
#pragma pack(pop)
--- gcc ---
struct Foo{
 char a;
 int  i[2];
}__attribute__ ((packed));

上の構造体でデータ境界を詰めてしまう。

JNIEXPORT void JNICALL Java_JClassHoge_CFunc(
 JNIEnv *env,
 jobject obj,
 jcharArray charar)
{
 jboolean isCp;
 // ここが実装上のC−Java間の差異を超える部分
 jchar *buf = env->GetCharArrayElements(charar,&isCp);
 Foo *stFoo = (Foo*)buf;
  :
 なんか代入
  :
 if(isCp==JNI_TRUE){ 
  // Javaはバッファをコピーしてよこす場合があるので一環性を保障しなければなら
ない
  env->ReleaseCharArrayElements(charar,buf,0);
 }
}

TADA 2004/08/13(金) 08:48:27
Bosscatさんありがとうございます。

まだJNIの処理は着手しておりません。
今は着手するに当たっての構想を考えております、申し訳ございません。
初めて行う処理ですので、色々お聞きしたく予め投稿させていただきました。

簡単なプログラムを作ってみます。参考にさせていただきますので、分からない時があれ
ばその時またお願い致します。

Bosscat 2004/08/13(金) 22:21:08
ちょっと、前回貼り付けたソースを実際検証してみました。
その結果、
CFunc(char[] charar);
では問題があることが判明しました!!(TT;
ワイドキャラとして扱われる場合があるようです。
なので、ワード境界1バイトで扱いたいのならば、正しくは
CFunc(byte[] bytear);
ですね・・・

当然C側もコレに伴って変更が必要です。

キチンと検証してから、書き込みなさい!という奴ですね・・・
すみません・・・

お騒がせしました。

古いスレッドには追加発言できません。