如何在 JNA Wrapper 端隐藏 C DLL 函数的一些参数?
How can I hide some parameters from C DLL function on JNA Wrapper side?
我已经使用 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(嵌入 initFunction(int firstValue, int secondValue, int thirdValue) 的 C DLL(具有 public int initFunction(int firstValue) 函数)。但我宁愿在java 端,以便不管理 2 个 C DLL。
另请参阅下面的 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);
}
}
感谢您的帮助。
这取决于您要存档的内容。如果你想让用户更容易调用 init,这是一个选项(使用 libc 中的 gethostname 进行演示),它使用 Java8 功能,允许向接口添加默认方法:
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());
}
}
同上思路,默认方法会把丑的部分隐藏起来。在这种情况下,虽然函数不是通过托管实例访问的,而是直接通过函数指针访问的。
我已经使用 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(嵌入 initFunction(int firstValue, int secondValue, int thirdValue) 的 C DLL(具有 public int initFunction(int firstValue) 函数)。但我宁愿在java 端,以便不管理 2 个 C DLL。
另请参阅下面的 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);
}
}
感谢您的帮助。
这取决于您要存档的内容。如果你想让用户更容易调用 init,这是一个选项(使用 libc 中的 gethostname 进行演示),它使用 Java8 功能,允许向接口添加默认方法:
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());
}
}
同上思路,默认方法会把丑的部分隐藏起来。在这种情况下,虽然函数不是通过托管实例访问的,而是直接通过函数指针访问的。