【问题标题】:How to cast a pointer to a c struct to jna structure如何将指向 c 结构的指针转换为 jna 结构
【发布时间】:2011-09-15 16:41:41
【问题描述】:

在将指向 C 结构的指针转换为 jna 结构时,我需要一些帮助。我正在使用 jna 从 dll 接收回调函数,该函数有一个参数是指向 C 结构的指针,当我尝试将指针强制转换为 jna 结构时,我得到错误的结构值。

那是 C 结构体:

typedef struct
{
   int x;
   int y;
}Point;
Point *gpt;

typedef struct
{
   int x;
   int y;
   Point pt1;
}Point2;
Point2 *gpt2;

这是 C 中的回调函数,带有指向 Point2 结构的指针(void *params):

void __stdcall PointCallback(void *params, int param_size)

所以,我在 java 中编写了这段代码来接收回调并获取原始结构:

// Point.java    
package Callback.UsePointLib;
import com.sun.jna.Structure;

public class Point extends Structure
{
   public static class ByValue extends Point implements Structure.ByValue {}
   public int x;
   public int y;
}

//Point2.java
package Callback.UsePointLib;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;

public class Point2 extends Structure {
       public int x;
       public int y;
       Point pt1;
       public Point2(Pointer p){
           super(p);
       }
}

回调实现:

//UsePointLib.java
public interface IFuncCallback extends StdCallCallback{
       void callback(Pointer Params, int ParamSize);
   }
   public class FuncCallback implements IFuncCallback{
    @Override
    public void callback(Pointer Params, int ParamSize) {
        Point2 pt2; // = new Point2();
        pt2 = new Point2(Params);
        System.out.println("pt2.x = "+pt2.x);        **<- I get zero here instead of four**
        System.out.println("pt2.y = "+pt2.y);        **<- I get zero here instead of five**
        System.out.println("pt2.pt1.x = "+pt2.pt1.x);**<- pt1 is null, throwing exception**
        System.out.println("pt2.pt1.y = "+pt2.pt1.y);**<- same as pt1.**
    }   
   }

我制作了一个 C 程序来访问 dll 并接收回调,它工作正常,它接收到正确的值。所以,问题是我的java代码。我尝试了许多替代方案,但均未成功。

拜托,如果能提供任何帮助,我将不胜感激。

谢谢,

费尔南多。


编辑

我已经修改了代码,它可以部分工作。

 //UsePointLib.java
    public interface IFuncCallback extends StdCallCallback{
           void callback(Pointer Params, int ParamSize);
       }
       public class FuncCallback implements IFuncCallback{
        @Override
        public void callback(Pointer Params, int ParamSize) {
            Point2 pt2; // = new Point2();
            pt2 = new Point2(Params);
                *pt2.read();*   **<--Modification**
            System.out.println("pt2.x = "+pt2.x);        **<- I get the correct value (four)**
            System.out.println("pt2.y = "+pt2.y);        **<- I get the correct value (five)**
            System.out.println("pt2.pt1.x = "+pt2.pt1.x);**<- pt1 is still null, throwing exception**
            System.out.println("pt2.pt1.y = "+pt2.pt1.y);**<- same as pt1.**
        }   
       }

【问题讨论】:

    标签: pointers casting callback structure jna


    【解决方案1】:

    在回调的上下文中,JNA 将在进入时自动调用 Structure.read,在退出时为任何 Structure 类型的参数调用 Structure.write。

    如果您将回调方法签名声明为使用适当子类的结构类型(在您的示例中为“Point2”),则与本机内存的复制应该是自动的。

    【讨论】:

    • 您好 Technomage,我不能子类化,因为回调基于先前的条件指向多个 c 结构。例如,一次调用 params 指向 struct PointX,另一次调用它指向 struct PointY,这与 PointX 完全不同。经过一些尝试,我使用传递接收到的指针的结构构造函数解决了这个问题。在构造函数中,我使用了 useMemory(Pointer p) 来映射本机内存。这是可能的,因为我知道每个调用中指向的 c 结构,所以我可以使用正确的 java 结构覆盖其构造函数。谢谢。
    • 如果使用 3.3.0 或更高版本,请使用 Structure(Pointer) ctor 而不是 useMemory(Pointer);后者将多余地分配内存。
    【解决方案2】:

    jna 文档说构造函数 Structure(Pointer) 将结构分配到预分配的内存上。它不会自动为您分配值。我认为这不是您想要的。

    将构造函数改为

    public Point2(){
        super();
    }
    public Point2(Point1 p){
        super();
        pt1.x = p.x;
        pt1.y = p.y;
    
        this.x = something;
        this.y = something;
    }
    

    【讨论】:

    • 您好 Abhijith,感谢您的帮助。我阅读了 jna doc,我知道,但是,我要做的是将 dll 内的结构中的数据复制到 java 内存中。
    • 它是一个 CTI 应用程序,dll 由 cti 卡供应商提供,回调是接收卡的事件(振铃、呼叫应答等)。因此,我将回调放在一个线程中,并使用消费者/生产者将事件数据通过队列传递到另一个线程。这就是原因,因为我需要将接收到的指针指向的内容复制到本地内存。我将编辑我的帖子以提出一种可能的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多