当前位置: 首页 > 知识库问答 >
问题:

我如何从JNA包装端的C DLL函数中隐藏一些参数?

酆耀
2023-03-14

我已经使用JNA成功包装了一个C DLL库。由于我不是C开发部分的所有者,所以我想隐藏我在Java端包装的C函数的一些参数。

更准确地说,我的Java代码如下:

public interface IJNALibrary extends Library {

    // INIT FUNCTION
    public int initFunction(int firstValue, int secondValue, int thirdValue);
}

在C端的*.h文件中有:

extern "C" CSAMPLE_API int initFunction (
    unsigned            firstValue,
    unsigned            secondValue,
    unsigned            thirdValue);

我的目的是直接将secondValue和thirdValue参数设置为1,从而向Java API用户隐藏这些参数。我不想让用户知道他可以更改这些参数的值。事实上,我想要这样的东西:

public interface IJNALibrary extends Library {

    // INIT FUNCTION
    public int initFunction(int firstValue);
}

initFunction(int firstValue)从C DLL部分调用initFunction(int firstValue,int secondValue,int thirdValue)。但这必须在Java包装器中完成,而不是从调用Java包装器的代码中完成。恐怕这是不可能的,是吗?除非我创建另一个C DLL(带有公共int initFunction(int firstValue)函数),该函数调用第一个C DLL(嵌入initFunction(int firstValue,int secondValue,int thirdValue))。

另请参阅下面的sample.java文件,该文件调用IJNALibrary接口中定义的映射方法。

public class Sample {

    static IJNALibrary IJNAFunctions;
    
    public static void main(String[] args) throws IOException {
    
        System.setProperty("jna.library.path", "./librayPath");
        
        // LOADING  LIBRARY
        IJNAFunctions = (IJNALibrary) Native.load("c", IJNALibrary.class);

        int firstValue = 1;
        int secondValue = 2;
        int thirdValue = 3;

        int initReturn = IJNAFunctions.initFunction(firstValue, secondValue, thirdValue);
    }
}

谢谢你的帮助。

共有1个答案

庾勇军
2023-03-14

这取决于您要存档的内容。如果您想让用户更容易调用init,这是一个选项(使用libc中的gethostname演示),它使用了一个Java 8特性,允许向接口添加默认方法:

public class TestDefaultMethod {
  public static interface LibC extends Library {
    LibC INSTANCE = Native.load("c", LibC.class);

    // Original binding of method
    int gethostname(byte[] name, int len);

    // Helper method to make it easier to call gethostname
    default String gethostname() {
        byte[] result = new byte[255];
        LibC.INSTANCE.gethostname(result, result.length);
        return Native.toString(result);
    }
  }

  public static void main(String[] args) {
    // Usage
    System.out.println(LibC.INSTANCE.gethostname());
  }
}

Java的开发人员通常不会对函数进行数组,因为函数会填充函数,而Java的开发人员也不会在单独的参数中传递数组的长度。这些是函数的C属性的工件。在包装函数中,分配一个数组,完成本机调用,然后打开包装数组。所有丑陋的C特长都隐藏在默认方法中。

如果您根本不想在Java上公开该方法(请注意,如果您的用户可以访问JNA库,他们可以绕过您的保护!),您可以直接使用函数指针:

public class TestDefaultMethod {

  public static interface LibC extends Library {
    NativeLibrary libc = NativeLibrary.getInstance("c");
    LibC INSTANCE = Native.load("c", LibC.class);

    default String gethostname() {
        byte[] result = new byte[255];
        libc.getFunction("gethostname").invokeInt(new Object[] {result, result.length});
        return Native.toString(result);
    }
  }

  public static void main(String[] args) {
    System.out.println(LibC.INSTANCE.gethostname());
  }
}

和上面的想法一样,默认的方法会隐藏难看的部分。在这种情况下,函数不是通过托管实例访问的,而是直接通过函数指针访问的。

 类似资料:
  • 本文向大家介绍PowerShell函数参数用星号隐藏的方法,包括了PowerShell函数参数用星号隐藏的方法的使用技巧和注意事项,需要的朋友参考一下 本文介绍在PowerShell中创建函数时,如何让函数的参数输入值的时候自动变成星号。 什么叫自动变成星号呢?举个例子,我们在登录一个邮箱时,输入用户时看到的是明文的,但我们在输入密码时,看到的是一个个增加的星号。在使用PowerShell自定义函

  • 我可以看到,当我逐步通过代码,C样式的强制转换直接到参数包构造函数。为什么这是,我做错了什么?如何防止参数包构造函数似乎隐藏用户定义的转换?

  • 我正在使用这个小包装插件: https://github.com/tsevdos/n包装器 基本布局如下: 正在初始化插件: 我使用select filters隐藏/显示childrevs,然后重新初始化插件。我想知道是否可以将隐藏的divs从包装计数中排除? 最后,我使用jQuery循环来显示包装的DIV,所以隐藏的DIV应该在包装内(但不计算)。否则,cycle将把每个隐藏的div视为一个项。

  • 我目前正在做一个项目,需要开发一个原生DLL(用C++)来访问Java应用程序。我选择了JNA来做桥接工作,我面临着从Java向C++函数传递正确的int值的问题。 简单地说,我有一个函数在C++中接受一个int值作为参数:(代码被剥离,方法被重命名以保持机密性) 是一种简单的方法,它使用将任何数据类型的值转换为。执行情况如下: 是从我在代码中使用的实际结构重命名的。是的数组。和都是共享内存中的全

  • 我在JLabel中有一些长文本,例如“Lorem ipsum dolor sit amet, consecetur adipiscing elit, se do eiusmod temor interdidunt ut labore et dolore magna aliqua”。如果用户调整窗口大小并且没有太多空间,我想隐藏一些文本。我想得到这样的东西“Lorem ipsum dolor sit

  • 在基类中,我有一个函数,它接受一个字符串文件名,构造一个功能集,并将其工作延迟到一个纯虚拟函数。 在子类中,我实现了这个虚拟函数。 在中,我有一个子类的实例,并使用一个文件名调用。我以为这将调用基类的非虚拟函数,该函数接受字符串参数,但这并不能编译。错误是: 掠夺。cpp:在函数“int main()”中: 掠夺。cpp:33:48:错误:调用“SubClass::GetDetections(co