How to Call C/C++ Libraries from Java Using JNA: A Practical Guide
This article explains how to access native C/C++ functions and complex structures from Java using JNI, JNA, and SWIG, compares their trade‑offs, provides type‑mapping tables, detailed code examples for struct definitions, passing, and callbacks, and offers practical tips for reliable cross‑language integration.
Background
During development of a Java SDK for a C/C++ library (UMStor), rewriting the SDK entirely in Java would be too labor‑intensive, so the author explores ways for Java to call native functions in .dll or .so files.
JNI
Java Native Interface (JNI) allows Java code to invoke native C/C++ functions and vice‑versa. While the JVM itself is native and platform‑specific, JNI abstracts away VM differences, enabling Java’s platform‑independent nature. Using JNI requires creating a wrapper shared library that follows SUN’s data structures, loading it from Java, and writing native methods that delegate to the original library.
JNA
Java Native Access (JNA) builds on JNI and provides a Java library that lets you call functions in a shared library directly, without writing additional native code. It simplifies development but is best suited for relatively simple C/C++ APIs; complex interfaces and data structures are not recommended.
SWIG
SWIG (Simplified Wrapper and Interface Generator) is an open‑source tool that generates language bindings (including Java) for C/C++ libraries. It still uses JNI underneath. For simple APIs JNA is preferable, but for complex interfaces SWIG is the better choice.
Basic Type Mapping
The following table (illustrated below) shows the correspondence between C types and Java types as defined by JNA, which usually suffices for cross‑language data conversion.
When calling across languages, prefer basic types and avoid complex structs because C struct layout (alignment, member order) can cause compatibility issues on the Java side.
Struct Definition
To access a C/C++ struct from Java, define a corresponding Java class extending Structure, include inner classes ByReference and ByValue, and override getFieldOrder() to match the native member order.
typedef struct A { B* b; void* args; int len; };
typedef struct B { int obj_type; }; public static class A extends Structure {
public B.ByReference b;
public PointerByReference args;
public int len;
public static class ByReference extends A implements Structure.ByReference {}
public static class ByValue extends A implements Structure.ByValue {}
@Override
protected List getFieldOrder() {
return Arrays.asList("b", "args", "len");
}
}
public static class B extends Structure {
public int obj_type;
public static class ByReference extends B implements Structure.ByReference {}
public static class ByValue extends B implements Structure.ByValue {}
@Override
protected List getFieldOrder() {
return Arrays.asList("obj_type");
}
}Struct Passing
When a Java method needs to pass a struct, use ByReference (pointer) or ByValue (copy). For simple data transfer, Pointer or PointerByReference can be used.
test_myFun(A.ByValue a) test_myFun(A.ByReference a) test_myFun(A.ByReference[] a) test_myFun(Pointer a) test_myFun(PointerByReference a) test_myFun(PointerByReference[] a)Callback Functions
To handle C functions that accept callbacks, define a Java interface extending Callback with a method matching the native signature, then implement it.
typedef bool (*test_cb)(const char *name);
int test_myFun(test_cb cb, const char *name, uint32_t flag); public interface testCallback extends Callback {
boolean invoke(String name);
} public class testCallbackImpl implements testCallback {
@Override
public int invoke(String name) {
System.out.printf("Invoke Callback " + name + " successfully!");
return true;
}
} int testMyFun(Callback cb, String name, int flag); int rc = testMyFun(new testCallbackImpl(), "helloworld", 1);Conclusion
The main difficulty with JNA lies in correctly defining and passing structs; once that is mastered, the rest of the integration becomes straightforward. For robust cross‑language calls, it is advisable to wrap functions and structs to simplify data exchange.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
UCloud Tech
UCloud is a leading neutral cloud provider in China, developing its own IaaS, PaaS, AI service platform, and big data exchange platform, and delivering comprehensive industry solutions for public, private, hybrid, and dedicated clouds.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
