davisusanibar commented on code in PR #13788: URL: https://github.com/apache/arrow/pull/13788#discussion_r937132510
########## docs/source/java/cdata.rst: ########## @@ -220,4 +223,259 @@ Let's create a Java class to test our bridge: C++-allocated array: [1, 2, 3, null, 5, 6, 7, 8, 9, 10] +Share an Int32 array from Java to C++ +===================================== + +Example: ``Share an Int32 array from Java to C++``: + +**Java Side** + +For this example, we will export a Java jar with all dependencies needed to +be readable by C++. + +.. code-block:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.example</groupId> + <artifactId>cpptojava</artifactId> + <version>1.0-SNAPSHOT</version> + <properties> + <maven.compiler.source>11</maven.compiler.source> + <maven.compiler.target>11</maven.compiler.target> + <arrow.version>8.0.0</arrow.version> + </properties> + <repositories> + <repository> + <id>arrow-nightly</id> + <url>https://nightlies.apache.org/arrow/java</url> + </repository> + </repositories> + <dependencies> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-c-data</artifactId> + <version>${arrow.version}</version> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-memory-netty</artifactId> + <version>${arrow.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <archive> + <manifest> + <mainClass> + ToBeCalledByCpp + </mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </project> + +.. code-block:: java + + import org.apache.arrow.c.ArrowArray; + import org.apache.arrow.c.ArrowSchema; + import org.apache.arrow.c.Data; + import org.apache.arrow.memory.BufferAllocator; + import org.apache.arrow.memory.RootAllocator; + import org.apache.arrow.vector.FieldVector; + import org.apache.arrow.vector.IntVector; + import org.apache.arrow.vector.VectorSchemaRoot; + + import java.util.Arrays; + + public class ToBeCalledByCpp { + final static BufferAllocator allocator = new RootAllocator(); + + public static void fillfieldvectorfromjavatocpp(long schema_id, long array_id){ + try (ArrowArray arrow_array = ArrowArray.wrap(array_id); + ArrowSchema arrow_schema = ArrowSchema.wrap(schema_id) ) { + Data.exportVector(allocator, populateFieldVectorToExport(), null, arrow_array, arrow_schema); + } + } + + public static FieldVector populateFieldVectorToExport(){ + IntVector intVector = new IntVector("int-to-export", allocator); + intVector.allocateNew(3); + intVector.setSafe(0, 1); + intVector.setSafe(1, 2); + intVector.setSafe(2, 3); + intVector.setValueCount(3); + System.out.println("[Java - side]: FieldVector: \n" + intVector); + return intVector; + } + + public static void fillvectorschemarootfromjavatocpp(long schema_id, long array_id){ + try (ArrowArray arrow_array = ArrowArray.wrap(array_id); + ArrowSchema arrow_schema = ArrowSchema.wrap(schema_id) ) { + Data.exportVectorSchemaRoot(allocator, populateVectorSchemaRootToExport(), null, arrow_array, arrow_schema); + } + } + + public static VectorSchemaRoot populateVectorSchemaRootToExport(){ + IntVector intVector = new IntVector("age-to-export", allocator); + intVector.setSafe(0, 10); + intVector.setSafe(1, 20); + intVector.setSafe(2, 30); + VectorSchemaRoot root = new VectorSchemaRoot(Arrays.asList(intVector)); + root.setRowCount(3); + System.out.println("[Java - side] VectorSchemaRoot: \n" + root.contentToTSVString()); + return root; + } + + public static void main(String[] args) { + populateFieldVectorToExport(); + populateVectorSchemaRootToExport(); + } + } + +Compile our Java code to generate our jar with all dependencies needed for. + +.. code-block:: shell + + $ mvn clean install + $ cp target/cpptojava-1.0-SNAPSHOT-jar-with-dependencies.jar cpptojava.jar + $ cp cpptojava.jar <c++_project_path> + +**C++ Side** + +This process fetch Java JVM references to call methods needed for, via the C Data Interface: + +.. code-block:: cpp + + #include <iostream> + #include <arrow/api.h> + #include <arrow/c/bridge.h> + #include <jni.h> + + JNIEnv* create_vm(JavaVM ** jvm) { + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[2]; + options[0].optionString = "-Djava.class.path=cpptojava.jar"; // java jar name + options[1].optionString = "-DXcheck:jni:pedantic"; + vm_args.version = JNI_VERSION_1_8; + vm_args.nOptions = 2; + vm_args.options = options; + int status = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args); + if (status < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n"); + return env; + } + + int main() { + JNIEnv* env; + JavaVM* jvm; + env = create_vm(&jvm); + if (env == NULL) return 1; + jclass javaClassToBeCalledByCpp = NULL; + javaClassToBeCalledByCpp = env ->FindClass("ToBeCalledByCpp"); + if ( javaClassToBeCalledByCpp != NULL ) { + jmethodID fillfieldvectorfromjavatocpp = NULL; + fillfieldvectorfromjavatocpp = env->GetStaticMethodID(javaClassToBeCalledByCpp, "fillfieldvectorfromjavatocpp", "(JJ)V"); + if ( fillfieldvectorfromjavatocpp != NULL ){ + struct ArrowSchema arrowSchema; + struct ArrowArray arrowArray; + printf("\n<<<<< C++ to Java for Arrays >>>>>\n"); + env->CallStaticVoidMethod(javaClassToBeCalledByCpp, fillfieldvectorfromjavatocpp, reinterpret_cast<uintptr_t>(&arrowSchema), reinterpret_cast<uintptr_t>(&arrowArray)); + auto resultImportArray = arrow::ImportArray(&arrowArray, &arrowSchema); + std::shared_ptr<arrow::Array> array = resultImportArray.ValueOrDie(); + auto int32_array = std::static_pointer_cast<arrow::Int32Array>(array); + const int32_t* data = int32_array->raw_values(); + for (int j = 0; j < int32_array->length(); j++){ + printf("[C++ - side]: Data ImportArray - array[%d] = %d\n", j, data[j]); + } + } else { + printf("Problem to read method fillfieldvectorfromjavatocpp\n"); + } + jmethodID fillvectorschemarootfromjavatocpp = NULL; + fillvectorschemarootfromjavatocpp = env->GetStaticMethodID(javaClassToBeCalledByCpp, "fillvectorschemarootfromjavatocpp", "(JJ)V"); + if ( fillvectorschemarootfromjavatocpp != NULL ){ + struct ArrowSchema arrowSchema; + struct ArrowArray arrowArray; + printf("\n<<<<< C++ to Java for RecordBatch >>>>>\n"); + env->CallStaticVoidMethod(javaClassToBeCalledByCpp, fillvectorschemarootfromjavatocpp, static_cast<long>(reinterpret_cast<uintptr_t>(&arrowSchema)), static_cast<long>(reinterpret_cast<uintptr_t>(&arrowArray))); + auto resultImportVectorSchemaRoot = arrow::ImportRecordBatch(&arrowArray, &arrowSchema); + std::shared_ptr<arrow::RecordBatch> recordBatch = resultImportVectorSchemaRoot.ValueOrDie(); Review Comment: Changed ########## docs/source/java/cdata.rst: ########## @@ -220,4 +223,259 @@ Let's create a Java class to test our bridge: C++-allocated array: [1, 2, 3, null, 5, 6, 7, 8, 9, 10] +Share an Int32 array from Java to C++ +===================================== + +Example: ``Share an Int32 array from Java to C++``: + +**Java Side** + +For this example, we will export a Java jar with all dependencies needed to +be readable by C++. + +.. code-block:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.example</groupId> + <artifactId>cpptojava</artifactId> + <version>1.0-SNAPSHOT</version> + <properties> + <maven.compiler.source>11</maven.compiler.source> + <maven.compiler.target>11</maven.compiler.target> + <arrow.version>8.0.0</arrow.version> + </properties> + <repositories> + <repository> + <id>arrow-nightly</id> + <url>https://nightlies.apache.org/arrow/java</url> + </repository> + </repositories> + <dependencies> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-c-data</artifactId> + <version>${arrow.version}</version> + </dependency> + <dependency> + <groupId>org.apache.arrow</groupId> + <artifactId>arrow-memory-netty</artifactId> + <version>${arrow.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <archive> + <manifest> + <mainClass> + ToBeCalledByCpp + </mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </project> + +.. code-block:: java + + import org.apache.arrow.c.ArrowArray; + import org.apache.arrow.c.ArrowSchema; + import org.apache.arrow.c.Data; + import org.apache.arrow.memory.BufferAllocator; + import org.apache.arrow.memory.RootAllocator; + import org.apache.arrow.vector.FieldVector; + import org.apache.arrow.vector.IntVector; + import org.apache.arrow.vector.VectorSchemaRoot; + + import java.util.Arrays; + + public class ToBeCalledByCpp { + final static BufferAllocator allocator = new RootAllocator(); + + public static void fillfieldvectorfromjavatocpp(long schema_id, long array_id){ + try (ArrowArray arrow_array = ArrowArray.wrap(array_id); + ArrowSchema arrow_schema = ArrowSchema.wrap(schema_id) ) { + Data.exportVector(allocator, populateFieldVectorToExport(), null, arrow_array, arrow_schema); + } + } + + public static FieldVector populateFieldVectorToExport(){ + IntVector intVector = new IntVector("int-to-export", allocator); + intVector.allocateNew(3); + intVector.setSafe(0, 1); + intVector.setSafe(1, 2); + intVector.setSafe(2, 3); + intVector.setValueCount(3); + System.out.println("[Java - side]: FieldVector: \n" + intVector); + return intVector; + } + + public static void fillvectorschemarootfromjavatocpp(long schema_id, long array_id){ + try (ArrowArray arrow_array = ArrowArray.wrap(array_id); + ArrowSchema arrow_schema = ArrowSchema.wrap(schema_id) ) { + Data.exportVectorSchemaRoot(allocator, populateVectorSchemaRootToExport(), null, arrow_array, arrow_schema); + } + } + + public static VectorSchemaRoot populateVectorSchemaRootToExport(){ + IntVector intVector = new IntVector("age-to-export", allocator); + intVector.setSafe(0, 10); + intVector.setSafe(1, 20); + intVector.setSafe(2, 30); + VectorSchemaRoot root = new VectorSchemaRoot(Arrays.asList(intVector)); + root.setRowCount(3); + System.out.println("[Java - side] VectorSchemaRoot: \n" + root.contentToTSVString()); + return root; + } + + public static void main(String[] args) { + populateFieldVectorToExport(); + populateVectorSchemaRootToExport(); + } + } + +Compile our Java code to generate our jar with all dependencies needed for. + +.. code-block:: shell + + $ mvn clean install + $ cp target/cpptojava-1.0-SNAPSHOT-jar-with-dependencies.jar cpptojava.jar + $ cp cpptojava.jar <c++_project_path> + +**C++ Side** + +This process fetch Java JVM references to call methods needed for, via the C Data Interface: + +.. code-block:: cpp + + #include <iostream> + #include <arrow/api.h> + #include <arrow/c/bridge.h> + #include <jni.h> + + JNIEnv* create_vm(JavaVM ** jvm) { + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[2]; + options[0].optionString = "-Djava.class.path=cpptojava.jar"; // java jar name + options[1].optionString = "-DXcheck:jni:pedantic"; + vm_args.version = JNI_VERSION_1_8; + vm_args.nOptions = 2; + vm_args.options = options; + int status = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args); + if (status < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n"); + return env; + } + + int main() { + JNIEnv* env; + JavaVM* jvm; + env = create_vm(&jvm); + if (env == NULL) return 1; + jclass javaClassToBeCalledByCpp = NULL; + javaClassToBeCalledByCpp = env ->FindClass("ToBeCalledByCpp"); + if ( javaClassToBeCalledByCpp != NULL ) { + jmethodID fillfieldvectorfromjavatocpp = NULL; + fillfieldvectorfromjavatocpp = env->GetStaticMethodID(javaClassToBeCalledByCpp, "fillfieldvectorfromjavatocpp", "(JJ)V"); + if ( fillfieldvectorfromjavatocpp != NULL ){ + struct ArrowSchema arrowSchema; + struct ArrowArray arrowArray; + printf("\n<<<<< C++ to Java for Arrays >>>>>\n"); + env->CallStaticVoidMethod(javaClassToBeCalledByCpp, fillfieldvectorfromjavatocpp, reinterpret_cast<uintptr_t>(&arrowSchema), reinterpret_cast<uintptr_t>(&arrowArray)); + auto resultImportArray = arrow::ImportArray(&arrowArray, &arrowSchema); + std::shared_ptr<arrow::Array> array = resultImportArray.ValueOrDie(); Review Comment: Changed -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@arrow.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org