首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在jnr ffi中使用结构与结构

如何在jnr ffi中使用结构与结构
EN

Stack Overflow用户
提问于 2016-07-14 08:25:58
回答 3查看 2.2K关注 0票数 1

我有以下c代码:

代码语言:javascript
复制
#include <stdio.h>

struct Second {
    int a_number;
};

struct Top {
    struct Second second;
};

void lets_go(struct Top *top) {
    printf("The number is %d\n", top->second.a_number);
}

我想用Java来做这个:

代码语言:javascript
复制
int main(void) {
    struct Top top = {{8}};
    lets_go(&top);
}

我还想使用约尔菲,所以我查看了这些测试,最后得到了以下结果:

代码语言:javascript
复制
package structs.playing;

import structs.playing.Program.Test.Top;
import structs.playing.Program.Test.Second;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;

public final class Program {

    public static interface Test {

        void lets_go(Top top);

        public static final class Second extends Struct {               
            public final Signed32 a_number = new Signed32();                
            public Second(final Runtime runtime) {
                super(runtime);
            }
        }

        public static final class Top extends Struct {              
            public Second second;                           
            public Top(final Runtime runtime) {
                super(runtime);
            }
        }
    }

    public static void main(final String[] args) {

        Test test = LibraryLoader.create(Test.class).load("test");
        Runtime runtime = Runtime.getRuntime(test);         
        Top top = new Top(runtime);
        Second second = new Second(runtime);
        top.second = second;
        second.a_number.set(7);         
        test.lets_go(top);
    }    
}

问题是a_number的值根本没有设置,所以我在输出中得到了一个垃圾值,例如:

代码语言:javascript
复制
The number is 46645760

那么,如何获得与C代码相同的信息呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-07-14 14:22:43

我已经想好了(顺便说一句,我知道成员应该是私有的,并且被包裹在属性中,但是我想使代码片段尽可能小,这不是生产质量代码).

如果将指针成员变量放入结构中,则可以在构造副坐标结构时使用它的内存,如……

代码语言:javascript
复制
package structs.playing;

import structs.playing.Program.Test.Top;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;

public final class Program {

    public static interface Test {

        void lets_go(Top top);

        public static final class Second extends Struct {

            public final Signed32 a_number = new Signed32();

            public Second(final Runtime runtime) {
                super(runtime);
            }           
        }

        public static final class Top extends Struct {

            private final Pointer secondPointer = new Pointer();            
            public final Second second;

            public Top(final Runtime runtime) {
                super(runtime);                             
                second = new Second(runtime); 
                second.useMemory(secondPointer.getMemory());
            }           
        }
    }

    public static void main(final String[] args) {

         Test test = LibraryLoader.create(Test.class).load("test");
         Runtime runtime = Runtime.getRuntime(test);         
         Top top = new Top(runtime);
         top.second.a_number.set(8);         
         test.lets_go(top);
    }
}
票数 2
EN

Stack Overflow用户

发布于 2016-10-27 13:56:22

编辑:我花了更多的时间看代码,我对创建结构的理解略有改变。

我相信您应该声明关于结构的所有内容并使其成为最终的,因为每次您声明一个新成员时,它都会向它所属的结构注册自己。

对于每个用例,struct中都有一些帮助函数。重载数组()方法允许您注册一个成员或Structs数组。内部()方法允许您注册单个结构。否则,您只需定义新成员对象,它们将自动注册。

例如:

代码语言:javascript
复制
struct Second {
    int a_number;
};

struct Top {
    struct Second second;
    struct Second seconds[5];
    int another_number;
    int more_numbers[5];
};

代表如下:

代码语言:javascript
复制
public final class Second extends Struct {
    public final Signed32 a_number = new Signed32();
    public Second(final Runtime runtime) {
        super(runtime);
    }
}

public final class Top extends Struct {              
    public final Second second = inner(new Second(getRuntime()));  
    public final Second[] seconds = array(new Second[5]);
    public final Signed32 another_number = new Signed32();
    public final Signed32[] more_numbers = array(new Signed32[5]);
    public Top(final Runtime runtime) {
        super(runtime);
    }
}

我相信正确的方法是使用接受的重载的Struct构造函数(Runtime,Struct)。https://github.com/jnr/jnr-ffi/blob/master/src/main/java/jnr/ffi/Struct.java#L129

代码语言:javascript
复制
protected Struct(Runtime runtime, Struct enclosing) {
    this(runtime);
    __info.alignment = enclosing.__info.alignment;
}

此构造函数强制封闭结构共享其内存。所以在你的例子中,我认为应该是这样的:

代码语言:javascript
复制
package structs.playing;

import structs.playing.Program.Test.Top;
import structs.playing.Program.Test.Second;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;

public final class Program {

    public static interface Test {

        void lets_go(Top top);

        public static final class Second extends Struct {               
            public final Signed32 a_number = new Signed32();                
            public Second(final Runtime runtime, final Struct enclosing) {
                super(runtime, enclosing);
            }
        }

        public static final class Top extends Struct {              
            public Second second;                           
            public Top(final Runtime runtime) {
                super(runtime);
            }
        }
    }

    public static void main(final String[] args) {

        Test test = LibraryLoader.create(Test.class).load("test");
        Runtime runtime = Runtime.getRuntime(test);         
        Top top = new Top(runtime);
        Second second = new Second(runtime, top);
        top.second = second;
        second.a_number.set(7);         
        test.lets_go(top);
    }    
}

请注意对第二个构造函数的更改,并注意到我将Top对象传递给了第二个对象,因此它知道top正在包围它。这是没有测试的,只是分享我在试图理解代码时发现的内容。

我认为在你的例子中发生的事情是,第二个对象是分配它自己的内存,托普对此一无所知。

如果这样做不起作用,我建议您做这样的事情:

代码语言:javascript
复制
public static final class Top extends Struct {              
    public Second second = new Second(getRuntime(), this);                           
    public Top(final Runtime runtime) {
        super(runtime);
    }
}
票数 5
EN

Stack Overflow用户

发布于 2016-07-14 09:06:05

当指定了结构时,如行中所示

代码语言:javascript
复制
top.second = second;

在您的Java代码中,结构是second复制到top.second中,以便它们成为不同内存区域中的独立实体。稍后,当您在下面的行中将7赋值给a_number属性second时:

代码语言:javascript
复制
second.a_number.set(7);

top.second的相应属性保持不变,因为它们不是同一个对象。

为了获得与C代码相同的结果,请尝试将main方法更改为:

代码语言:javascript
复制
public static void main(final String[] args) {

    Test test = LibraryLoader.create(Test.class).load("test");
    Runtime runtime = Runtime.getRuntime(test);         
    Top top = new Top(runtime);
    top.second.a_number.set(8);         
    test.lets_go(top);
}

没有必要初始化一个新的Second对象,因为作为初始化Top对象的一部分,已经为top.second分配了内存。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38369104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档