在保留本机typedef类的同时映射JNA中的原始类型

huangapple go评论82阅读模式
英文:

Mapping primitive type in JNA while keeping the native typedef class

问题

我在我的DLL中有这个类型定义:

typedef int FMOD_MEMORY_TYPE;

我能否在Java中为此创建一个类,以便我知道FMOD_MEMORY_TYPE只是一个int

public final class FMOD_MEMORY_TYPE {
    public int value;
}

我假设它占用相同的内存?

这个类型经常传递给函数,如果在Java中它有自己的类似于typedef的定义,将会更容易。如果不行,我该如何在Java中进行类型映射?

基本上它只是一个int,但是如果必须将所有出现的情况都替换为int,会花费很多时间,使用类似typedef的方法会更容易。

基本上,我希望能够像这样映射代码:
(C):

void some_function(FMOD_MEMORY_TYPE argument);

<=> Java:

public void some_function(FMOD_MEMORY_TYPE arg);

而不是:

public void some_function(int arg);
英文:

I have this type defined in my DLL:

typedef int FMOD_MEMORY_TYPE;

Can I make a class for this in Java so I will know FMOD_MEMORY_TYPE is just an int?

public final class FMOD_MEMORY_TYPE {
	public int value;
}

As I presume it takes the same amount of memory?

This type is passed into functions a lot and it would make it a lot easier if in Java it had its own typedef almost too. If not, how can I make some of mapping to a type in Java?

Essentially it's just an int but having to replace all occurrences with int would take a lot of time and this would be easier.

Essentially I Want to be able to map the code like this:
(C):

void some_function(FMOD_MEMORY_TYPE argument);

<=> Java:

public void some_function(FMOD_MEMORY_TYPE arg);

instead of:

public void some_function(int arg);

答案1

得分: 0

是的,您可以为基本数据类型创建一个包装类,但并不像您描述的那么简单。

包装类为您提供了一些方便,以便像您请求的那样移植代码,同时还提供了类型安全性。这个类在Java端会占用一些额外的内存,因为您需要为整个对象分配空间,而不仅仅是基本数据类型的内存。并且在存储和检索内部值时会有一点点性能损耗。然而,如果这些权衡对您来说是值得的,并且不用在性能敏感的应用程序中使用,那就没有问题。

但是,您不能像您在问题中描述的那样仅仅使用一个类,而是需要为JNA添加附加功能,以确定对象的字节大小及其相应的本机类型。具体来说,您需要实现NativeMapped接口。最简单的方法是通过扩展已经为您完成这些工作的现有JNA类来实现。

对于整数类型定义,我建议您创建一个扩展IntegerType的类型,并为您提供访问那些方法的方式。所以在您的情况下,我会这样做:

public final class FMOD_MEMORY_TYPE extends IntegerType {

    public static final int SIZE = 4; // 字节

    public FMOD_MEMORY_TYPE() {
        this(0);
    }

    public FMOD_MEMORY_TYPE(int value) {
        super(SIZE, value);
    }
}

通过这样做,您将继承IntegerTypesetValue()方法,并继承所有核心Java Number 类方法,比如 intValue()

您还可以选择实现Comparable接口或根据需要添加其他方法。

在JNA的WinDef类等地方有很多示例。

英文:

Yes, you can create a wrapper class for primitives, but not quite as simply as you describe.

A wrapper class gives you some ease in porting code as you've requested, as well as type safety. The class will take a little bit more memory on the Java side as you're allocating space for an entire object instead of simply the memory for a primitive. And there will be a tiny performance hit for storing and retrieving the internal value. However, if these trade-offs are worth it to you and aren't used in a performance-sensitive application, it's not a problem.

However, you can't just use a class as you've described in your question without adding additional functionality for JNA to determine the byte size of the object and its corresponding native equivalent. Specifically, you would have to implement the NativeMapped interface. This is most easily done by extending an existing JNA class which already does this work for you.

For an integer typedef, I would recommend that you create a type that extends IntegerType and provides you access to those methods. So in your case, I'd do:

public final class FMOD_MEMORY_TYPE extends IntegerType {

    public static final int SIZE = 4; // bytes

    public FMOD_MEMORY_TYPE() {
        this(0);
    }

    public FMOD_MEMORY_TYPE(int value) {
        super(SIZE, value);
    }
}

Doing this will will inherit setValue() from IntegerType and inherit all of the core Java Number class methods like intValue().

You could also choose to implement Comparable or add other methods as needed.

There are plenty of examples in JNA's WinDef class, among others.

huangapple
  • 本文由 发表于 2020年9月1日 06:10:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63678824.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定