使用JNA的时候除了Native.loadlibrary用了JNA的东西,还有什么地方用啊?
传递到dll函数的参数也要都用JNA提供的数据类型吗?请问dll函数需要pChar类型的变量,我怎么定义啊?和pointer\memory有关系吗?
请大家帮帮忙,非常感谢◎!
传递到dll函数的参数也要都用JNA提供的数据类型吗?请问dll函数需要pChar类型的变量,我怎么定义啊?和pointer\memory有关系吗?
请大家帮帮忙,非常感谢◎!
2)dll函数需要pChar类型的变量,我怎么定义啊?
DELPHI DLL 是需要一个PChar的数组作为参数的,问:JAVA中如何向它传递参数?
用JNA时不要用JAVA中的byte[],楼主要使用JNA中的ByteByReference[]即ByteByReference数组来传递。
int DUABind(struct UserInfo *puserinfo,
char *dsaip_address,
int port_no,
SOCKET *psock,
int bindseconds)delphi调用该dll时的接口描述:
function DUABind(puserinfo : PUserInfo;
dsaip_address : pchar;
port_no : integer;
var psock : TSocket;
bindseconds : integer
):integer;cdecl;external CLIENT_DLLNAME name 'DUABind';
使用JNA时如何写接口?
我这样写的:
int DUABind(TUserInfo.ByReference puserinfo,
byte[] dsaip_address ,
int port_no,
Socket psock,
int bindseconds);其中TUserInfo定义如下
public class TUserInfo extends Structure implements Invariable{
public static class ByReference extends TUserInfo implements Structure.ByReference{}
public static class ByValue extends TUserInfo implements Structure.ByValue{} public byte[] Name = new byte[20]; //登录名
public byte[] Password = new byte[20]; //登录密码
}函数返回参数0-8,0表示连接成功,但返回3(网络连接失败),源码中是在initsock函数时没有成功,所以返回3 ,但是没有报错
应该是第二个参数传递错误(pchar),请问楼上,其他的参数有没有问题?非常感谢
答:一个PChar,用ByteByReference。
用法是:
ByteByReference mybbr = new ByteByReference();
Memory mymem = new Memory(20);//20个c字符
mymem.setString(0, "myip");
mybbr.setPointer(mymem.getPointer(0));
我昨天试过你的方法了 ,应该是对的,但是返回结果还是不对,返回的结果是对socket的绑定错误(第四个参数)
这个结果只与char *dsaip_address,和int port_no,有关,很郁闷啊,不知道还可能是什么原因呢?P.S.:第四个参数我是这样定义的 Socket sock = null;
这个函数正确后,对sock进行初始化。
答:根据你目前所提供的信息,我猜测是在执行“源码中在initsock函数时”,它当中的代码在执行bind()函数时时发生的错误。能否给出bind的错误信息,这样我就知道是错误在何处.bind发生的错误有:EADDRINUSE(给定的地址已在使用当中),EBADF(bind()函数第一个参数sockfd非法-如sockfd为空),EINVAL(bind()函数第一个参数sockfd已经bind给其它地址了),ENOTSOCK(bind()函数第一个参数sockfd不是一个正确的sockfd).只有第一个错误EADDRINUSE与第三个错误EINVAL与char *dsaip_addresss相关,而这个错误明确表示:char *dsaip_addresss已正确地传入进去了。因此:这个错误信息表明是一个网络程序的逻辑错误。
因此:请你根据你程序中的bind的错误信息与上述我给出的四种错误信息对比,就能知道问题在何处了。
if(PackDAPRequestOrResult(&duainfo,package,&package_len,0))
{
return 2;//打包失败
}
printf("after packdaprequestorresult package len:%d\n",package_len);//yfzy
if(InitSocket(dsaip_address,port_no,psock))
{
return 3;//网络连接失败
}
InitID(id_name,id_add,Port_dapConnection,1);
//打公共上三层数据包
printf("after id_add:%d\n",id_add);//yfzy
if(Common_pack(package,&package_len,(unsigned char **)id_add,3,MAX_BINDINFO_LENGTH))
{
ExitSocket(*psock);
return 4;//打上三层数据包错误
}但是我实在是不知道你说的bind的错误怎么查看,很菜啊,不好意思,能告诉我怎么知道bind的错误吗?DLL中还有个DUAUnBind(SOCKET× psock),我在JAVA中只测这个函数
如果Socket psock = null;则返回没有这个socket
如果Socket psock = new Socket("192.168.0.87",2509);,则返回Unsupported argument type java.net.socket.net.Socket at parameter 0 of function DUAUnBind.
是不是JNA里也有相应的对应类型,不是java的Socket呢?这位大哥实在是太感谢你了!!
{
return 3;//网络连接失败
}
这一部分代码,当出错时只返回3,确实将详细的错误信息全丢失了。这样就不知道真正的错误信息及原因了。
2)我认为,问题真正的原因十分可能是在这儿:DELPHI中和TSOCKET本质是一个Integer,又是通过
var psock : TSocket; 因而psock本质上是一个Integer的指针。而这个类型正好对应原C++中的SOCKET *psock;因为在C++中,SOCKET就是一个int。现在我们将它对应JAVA中的java.net.Socket类,我十分怀疑,这就是问题的根源。
3)若真是这样,问题比较棘手。因为:无论C++的SOCKET,还是DELPHI中的TSOCKET,本质是int,其真正的含义是网络通信的socket的fd来处理的(fd是int),而这个返回出来的socket fd,如何转换成java.net.Socket类的对象,这才是真正困难的地方。(JNA对这一个没有提供转换)。通过JNA,如IntByReference,是可以将这个fd(网络连接成功的socket的fd)的值带出来,但带出来后在JAVA中怎么使用它呢?即:如何将这个已连接成功的socket的fd,转换成java.net.Socket对象在JAVA中使用呢?这才是真正困难的地方。
目前还没有想到一个好的办法。还想思考中
这个psock参数,你JAVA程序中要使用吗?若不要使用,则直接用JNA中的IntByReference来表达SOCKET* psock。若要使用,则比较麻烦,;因为JNA中对这一个(socket fd 转换成java.net.Socket类的对象)没有提供转换。
非常高兴的告诉你,结果已经不是3了
很郁闷的再告诉你现在结果是7...
相应的源码是这样的:
if(status !=1)
{
ExitSocket(*psock);
return 6;//注册信息接收失败或超时;
}
printf("before common_unpack\n");//yfzy
if(status=Common_unpack(recv_buf,&package_len,id_val))
{
ExitSocket(*psock);
printf("after common_unpack\n");//yfzy
return 7;//解上三层数据包错误
}我再看看Common_unpack(recv_buf,&package_len,id_val)很开心!!非常感谢你!对了,我把pchar用byte[],socket*用IntByReference,3那一段代码就过去了,用ByteByReference还是出3,不知道为什么
public class TUserInfo extends Structure implements Invariable{
public static class ByReference extends TUserInfo implements Structure.ByReference{}
public static class ByValue extends TUserInfo implements Structure.ByValue{} public byte[] Name = new byte[20]; //登录名
public byte[] Password = new byte[20]; //登录密码
} 原来的:
name: array[0..19] of char;
password :array[0..19] of char;不知道这样对不对。返回值为‘7’,表示服务器端解包错误,所以我觉得应该是传过去的参数不太对既然socket能建立那么就剩结构体这一个参数了。。
byte[] dsaip_address ,
int port_no,
Socket psock,
int bindseconds); 其中TUserInfo定义如下
public class TUserInfo extends Structure implements Invariable{
public static class ByReference extends TUserInfo implements Structure.ByReference{}
public static class ByValue extends TUserInfo implements Structure.ByValue{} public byte[] Name = new byte[20]; //登录名
public byte[] Password = new byte[20]; //登录密码
}
既然socket能建立那么就剩结构体这一个参数了。。
答:这样定义试试:
int DUABind(TUserInfo puserinfo,...
public class TUserInfo extends Structure implements Invariable{
public byte[] Name = new byte[20]; //登录名
public byte[] Password = new byte[20]; //登录密码
}
也是正确的。
但其它看起来,都是正确的啊
您说的第一种方法我试过,直接就有异常了,第二种应该是对的。我觉得好像和结构体的初始化有关系。
我把byte[]的初始化过程用byte[] UserInfo.Name = Native.getBytes(String s)(我原来用的就是String s;UserInfo.Name =s.getbytes),结果变成1了
源码中1的判断在7的后面,说是‘注册失败,非法用户’好像又进了一步(不知道能不能这么想啊!)。Native.getBytes(String s)是以/0结尾的,
不知道是不是和没有这个结尾有关系,还没有找到不以/0结尾的方法。我在想是不是所有函数参数都要用JNA自己定义的变量呢?包括初始化似乎也要用JNA的方法。
又不知道该怎么办了呵呵
public class TUserInfo extends Structure implements Invariable{
public static class ByReference extends TUserInfo implements Structure.ByReference{}
public static class ByValue extends TUserInfo implements Structure.ByValue{} public byte[] Name = new byte[20]; //登录名
public byte[] Password = new byte[20]; //登录密码
} 原来的:
name: array[0..19] of char;
password :array[0..19] of char; 如何初始化赋值?
我感觉应该是这样:(因为:Name 与 Password[color=#FF0000]必须是20个字节的数组[/color)byte[] tmp=Native.getBytes(s);或者是:byte[] tmp=s.getBytes();
然后利用:System.arraycopy(...)将这个tmp数组内容(可有少于20个字节)拷贝到20个字节的Name 与 Password中。
啊,您真的是经验老到阿,确实是你说的那样子,开始用System.arraycopy(...)之后还是有问题,后来又发现我师兄把密码给错了,害我折腾了老半天,已经能正常输出0了
呵呵,非常感谢。关于那个socket的问题,确实需要解决的,还有好多函数的参数直接就用的DUABind之后产生的socket值,我直接将sock输入DUAUnBind好像有问题。socket的问题确实很麻烦阿总之,非常感谢你