我如何隐藏一些参数从C DLL函数在JNA包装方?



我已经成功地使用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 Wrapper内部完成,而不是从调用java Wrapper的代码中完成。恐怕这是不可能的,是吗?除非我创建另一个C DLL(与公共int initFunction(int firstValue)函数)调用第一个C DLL(嵌入initFunction(int firstValue, int secondValue, int thirdValue)。但我宁愿在java端这样做,以免管理2个C dll。

参见下面的Sample.java文件,该文件调用ijnlibrary接口中定义的映射方法。

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);
}
}

谢谢你的帮助。

这取决于您想要归档的内容。如果您想让用户更容易调用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());
}
}
与上面的想法相同,默认方法将隐藏难看的部分。在这种情况下,虽然不是通过托管实例访问函数,而是直接通过函数指针访问。

最新更新