1 % Using Panama "foreign" JDK 2 3 # Using Panama "foreign" JDK 4 5 There are two ways to get a panama foreign branch JDK. 6 7 1. Locally build "foreign" branch of panama repo [http://hg.openjdk.java.net/panama/dev/](http://hg.openjdk.java.net/panama/dev/) 8 2. Download pre-built panama "foreign" early access binaries from [http://jdk.java.net/panama/](http://jdk.java.net/panama/) 9 10 Using foreign function call in Java involves the following three steps: 11 12 1. Use **jextract** tool to generate java interface for your C header file(s) 13 2. Use **java.foreign** API to create ("bind") implementation for C header interfaces 14 3. Invoke C functions via the jextracted Java interface 15 16 ## Embedding Python interpreter in your Java program (Mac OS) 17 18 ### jextract a Jar file for Python.h 19 20 ```sh 21 22 jextract -l python2.7 \ 23 -rpath /System/Library/Frameworks/Python.framework/Versions/2.7/lib \ 24 --exclude-symbols .*_FromFormatV\|_.*\|PyOS_vsnprintf\|.*_VaParse.*\|.*_VaBuild.*\|PyBuffer_SizeFromFormat\|vasprintf\|vfprintf\|vprintf\|vsprintf \ 25 -t org.python \ 26 /usr/include/stdio.h /usr/include/stdlib.h /usr/include/python2.7/Python.h \ 27 -o python.jar 28 29 ``` 30 31 ### Java program that uses extracted Python interface 32 33 ```java 34 35 // import java.foreign packages 36 import java.foreign.Libraries; 37 import java.foreign.Scope; 38 import java.foreign.memory.Pointer; 39 40 // import jextracted python 'header' classes 41 import static org.python.Python_h.*; 42 import static org.python.pythonrun_h.*; 43 44 public class PythonMain { 45 public static void main(String[] args) { 46 Py_Initialize(); 47 try (Scope s = Scope.newNativeScope()) { 48 PyRun_SimpleStringFlags(s.allocateCString( 49 "print(sum([33, 55, 66])); print('Hello from Python!')\n"), 50 Pointer.nullPointer()); 51 } 52 Py_Finalize(); 53 } 54 } 55 56 ``` 57 58 ### Running the Java code that calls Python interpreter 59 60 ```sh 61 62 javac -cp pythor.jar PythonMain.java 63 64 java -cp python.jar:. PythonMain 65 66 ``` 67 68 ## Embedding Python interpreter in your Java program (Ubuntu 16.04) 69 70 ### jextract a Jar file for Python.h 71 72 ```sh 73 74 jextract -l python2.7 \ 75 -rpath /usr/lib/python2.7/config-x86_64-linux-gnu \ 76 --exclude-symbols .*_FromFormatV\|_.*\|PyOS_vsnprintf\|.*_VaParse.*\|.*_VaBuild.*\|PyBuffer_SizeFromFormat\|vasprintf\|vfprintf\|vprintf\|vsprintf \ 77 -t org.python \ 78 /usr/include/stdio.h /usr/include/stdlib.h /usr/include/python2.7/Python.h \ 79 -o python.jar 80 81 ``` 82 83 ### Compiling and Running Python Java example 84 85 Follow the instructions from the Mac OS section 86 87 ## Using BLAS library 88 89 BLAS is a popular library that allows fast matrix and vector computation: [http://www.netlib.org/blas/](http://www.netlib.org/blas/). 90 91 ### Installing OpenBLAS (Mac OS) 92 93 On Mac, blas is available as part of the OpenBLAS library: [https://github.com/xianyi/OpenBLAS/wiki](https://github.com/xianyi/OpenBLAS/wiki) 94 95 OpenBLAS is an optimized BLAS library based on GotoBLAS2 1.13 BSD version. 96 97 You can install openblas using HomeBrew 98 99 ```sh 100 101 brew install openblas 102 103 ``` 104 105 It installs include and lib directories under /usr/local/opt/openblas 106 107 ### Installing OpenBLAS (Ubuntu 16.04) 108 109 On Ubuntu, blas is distributed as part of the atlas library: [http://math-atlas.sourceforge.net/](http://math-atlas.sourceforge.net/). 110 111 You can install atlas using apt 112 113 ```sh 114 115 sudo apt-get install libatlas-base-dev 116 117 ``` 118 119 This command will install include files under `/usr/include/atlas` and corresponding libraries under `/usr/lib/atlas-dev`. 120 121 122 ### jextracting cblas.h (MacOS) 123 124 The following command can be used to extract cblas.h on MacOs 125 126 ```sh 127 128 jextract -C "-D FORCE_OPENBLAS_COMPLEX_STRUCT" \ 129 -L /usr/local/opt/openblas/lib -I /usr/local/opt/openblas \ 130 -l openblas -t blas -infer-rpath /usr/local/opt/openblas/include/cblas.h \ 131 -o cblas.jar 132 133 ``` 134 135 The FORCE_OPENBLAS_COMPLEX_STRUCT define is needed because jextract does not 136 yet handle C99 `_Complex` types. The rest of the options are standard ones. 137 138 ### jextracting cblas.h (Ubuntu 16.04) 139 140 The following command can be used to extract cblas.h on Ubuntu 141 142 ```sh 143 144 jextract -L /usr/lib/atlas-base -I /usr/include/atlas/ \ 145 -l cblas -t blas -infer-rpath \ 146 /usr/include/atlas/cblas.h -o cblas.jar 147 148 ``` 149 150 ### Java sample code that uses cblas library 151 152 ```java 153 154 import blas.cblas; 155 156 import static blas.cblas_h.*; 157 158 import java.foreign.NativeTypes; 159 import java.foreign.Scope; 160 import java.foreign.memory.Array; 161 162 public class TestBlas { 163 public static void main(String[] args) { 164 @cblas.CBLAS_ORDER int Layout; 165 @cblas.CBLAS_TRANSPOSE int transa; 166 167 double alpha, beta; 168 int m, n, lda, incx, incy, i; 169 170 Layout = CblasColMajor; 171 transa = CblasNoTrans; 172 173 m = 4; /* Size of Column ( the number of rows ) */ 174 n = 4; /* Size of Row ( the number of columns ) */ 175 lda = 4; /* Leading dimension of 5 * 4 matrix is 5 */ 176 incx = 1; 177 incy = 1; 178 alpha = 1; 179 beta = 0; 180 181 try (Scope sc = Scope.newNativeScope()){ 182 Array<Double> a = sc.allocateArray(NativeTypes.DOUBLE, m * n); 183 Array<Double> x = sc.allocateArray(NativeTypes.DOUBLE, n); 184 Array<Double> y = sc.allocateArray(NativeTypes.DOUBLE, n); 185 /* The elements of the first column */ 186 a.set(0, 1.0); 187 a.set(1, 2.0); 188 a.set(2, 3.0); 189 a.set(3, 4.0); 190 /* The elements of the second column */ 191 a.set(m, 1.0); 192 a.set(m + 1, 1.0); 193 a.set(m + 2, 1.0); 194 a.set(m + 3, 1.0); 195 /* The elements of the third column */ 196 a.set(m * 2, 3.0); 197 a.set(m * 2 + 1, 4.0); 198 a.set(m * 2 + 2, 5.0); 199 a.set(m * 2 + 3, 6.0); 200 /* The elements of the fourth column */ 201 a.set(m * 3, 5.0); 202 a.set(m * 3 + 1, 6.0); 203 a.set(m * 3 + 2, 7.0); 204 a.set(m * 3 + 3, 8.0); 205 /* The elemetns of x and y */ 206 x.set(0, 1.0); 207 x.set(1, 2.0); 208 x.set(2, 1.0); 209 x.set(3, 1.0); 210 y.set(0, 0.0); 211 y.set(1, 0.0); 212 y.set(2, 0.0); 213 y.set(3, 0.0); 214 215 cblas_dgemv(Layout, transa, m, n, alpha, a.elementPointer(), lda, x.elementPointer(), incx, beta, 216 y.elementPointer(), incy); 217 /* Print y */ 218 for (i = 0; i < n; i++) 219 System.out.print(String.format(" y%d = %f\n", i, y.get(i))); 220 } 221 } 222 } 223 224 ``` 225 226 ### Compiling and running the above cblas samples 227 228 ```sh 229 230 javac -cp cblas.jar TestBlas.java 231 232 java -cp cblas.jar:. TestBlas 233 234 ``` 235 236 ## Using LAPACK library (Ubuntu) 237 238 On Ubuntu, the same steps used to install the blas (via atlas) library also install headers and libraries for the LAPACK library, a linear algebra computation library built on top of blas. 239 240 ### jextracting clapack.h (Ubuntu 16.04) 241 242 The following command can be used to extract the LAPACK header: 243 244 ```sh 245 246 jextract -L /usr/lib/atlas-base/atlas -I /usr/include/atlas/ \ 247 -l lapack -t lapack -infer-rpath /usr/include/atlas/clapack.h -o clapack.jar 248 249 ``` 250 251 ### Java sample code that uses LAPACK library 252 253 ```java 254 import java.foreign.NativeTypes; 255 import java.foreign.Scope; 256 import java.foreign.memory.Array; 257 258 import static lapack.clapack_h.*; 259 import static lapack.cblas_h.*; 260 261 public class TestLapack { 262 public static void main(String[] args) { 263 264 /* Locals */ 265 try (Scope sc = Scope.newNativeScope()) { 266 Array<Double> A = sc.allocateArray(NativeTypes.DOUBLE, new double[]{ 267 1, 2, 3, 4, 5, 1, 3, 5, 2, 4, 1, 4, 2, 5, 3 268 }); 269 Array<Double> b = sc.allocateArray(NativeTypes.DOUBLE, new double[]{ 270 -10, 12, 14, 16, 18, -3, 14, 12, 16, 16 271 }); 272 int info, m, n, lda, ldb, nrhs; 273 274 /* Initialization */ 275 m = 5; 276 n = 3; 277 nrhs = 2; 278 lda = 5; 279 ldb = 5; 280 281 /* Print Entry Matrix */ 282 print_matrix_colmajor("Entry Matrix A", m, n, A, lda ); 283 /* Print Right Rand Side */ 284 print_matrix_colmajor("Right Hand Side b", n, nrhs, b, ldb ); 285 System.out.println(); 286 287 /* Executable statements */ 288 // printf( "LAPACKE_dgels (col-major, high-level) Example Program Results\n" ); 289 /* Solve least squares problem*/ 290 info = clapack_dgels(CblasColMajor, CblasNoTrans, m, n, nrhs, A.elementPointer(), lda, b.elementPointer(), ldb); 291 292 /* Print Solution */ 293 print_matrix_colmajor("Solution", n, nrhs, b, ldb ); 294 System.out.println(); 295 System.exit(info); 296 } 297 } 298 299 static void print_matrix_colmajor(String msg, int m, int n, Array<Double> mat, int ldm) { 300 int i, j; 301 System.out.printf("\n %s\n", msg); 302 303 for( i = 0; i < m; i++ ) { 304 for( j = 0; j < n; j++ ) System.out.printf(" %6.2f", mat.get(i+j*ldm)); 305 System.out.printf( "\n" ); 306 } 307 } 308 } 309 ``` 310 311 ### Compiling and running the above LAPACK sample 312 313 ```sh 314 315 javac -cp clapack.jar TestLapack.java 316 317 java -cp clapack.jar:. TestLapack 318 319 ``` 320 321 ## Using LAPACK library (Mac OS) 322 323 On Mac OS, lapack is installed under /usr/local/opt/lapack directory. 324 325 ### jextracting lapacke.h 326 327 The following command can be used to extract the LAPACK header. These are too many symbols in lapacke.h 328 and so jextract throws too many constant pool entries (IllegalArgumentException). To workaround, we 329 include only the symbols used in the Java sample code below. 330 331 ```sh 332 333 jextract --include-symbols LAPACKE_dgels\|LAPACK_COL_MAJOR \ 334 -L /usr/local/opt/lapack/lib -I /usr/local/opt/lapack/ \ 335 -l lapacke -t lapack -infer-rpath /usr/local/opt/lapack/include/lapacke.h -o clapack.jar 336 337 ``` 338 ### Java sample code that uses LAPACK library 339 340 ```java 341 342 import java.foreign.NativeTypes; 343 import java.foreign.Scope; 344 import java.foreign.memory.Array; 345 346 import static lapack.lapacke_h.*; 347 348 public class TestLapack { 349 public static void main(String[] args) { 350 351 /* Locals */ 352 try (Scope sc = Scope.newNativeScope()) { 353 Array<Double> A = sc.allocateArray(NativeTypes.DOUBLE, new double[]{ 354 1, 2, 3, 4, 5, 1, 3, 5, 2, 4, 1, 4, 2, 5, 3 355 }); 356 Array<Double> b = sc.allocateArray(NativeTypes.DOUBLE, new double[]{ 357 -10, 12, 14, 16, 18, -3, 14, 12, 16, 16 358 }); 359 int info, m, n, lda, ldb, nrhs; 360 361 /* Initialization */ 362 m = 5; 363 n = 3; 364 nrhs = 2; 365 lda = 5; 366 ldb = 5; 367 368 /* Print Entry Matrix */ 369 print_matrix_colmajor("Entry Matrix A", m, n, A, lda ); 370 /* Print Right Rand Side */ 371 print_matrix_colmajor("Right Hand Side b", n, nrhs, b, ldb ); 372 System.out.println(); 373 374 /* Executable statements */ 375 // printf( "LAPACKE_dgels (col-major, high-level) Example Program Results\n" ); 376 /* Solve least squares problem*/ 377 info = LAPACKE_dgels(LAPACK_COL_MAJOR, (byte)'N', m, n, nrhs, A.elementPointer(), lda, b.elementPointer(), ldb); 378 379 /* Print Solution */ 380 print_matrix_colmajor("Solution", n, nrhs, b, ldb ); 381 System.out.println(); 382 System.exit(info); 383 } 384 } 385 386 static void print_matrix_colmajor(String msg, int m, int n, Array<Double> mat, int ldm) { 387 int i, j; 388 System.out.printf("\n %s\n", msg); 389 390 for( i = 0; i < m; i++ ) { 391 for( j = 0; j < n; j++ ) System.out.printf(" %6.2f", mat.get(i+j*ldm)); 392 System.out.printf( "\n" ); 393 } 394 } 395 } 396 397 ``` 398 399 ### Compiling and running the above LAPACK sample 400 401 ```sh 402 403 javac -cp clapack.jar TestLapack.java 404 405 java -cp clapack.jar:. TestLapack 406 407 ``` 408 409 ## Using libproc library to list processes from Java (Mac OS) 410 411 ### jextract a jar file for libproc.h 412 413 jextract -t org.unix -lproc -rpath /usr/lib -o libproc.jar /usr/include/libproc.h 414 415 ### Java program that uses libproc to list processes 416 417 ```java 418 419 import java.foreign.*; 420 import java.foreign.memory.*; 421 import static org.unix.libproc_h.*; 422 423 public class LibprocMain { 424 private static final int NAME_BUF_MAX = 256; 425 426 public static void main(String[] args) { 427 // Scope for native allocations 428 try (Scope s = Scope.newNativeScope()) { 429 // get the number of processes 430 int numPids = proc_listallpids(Pointer.nullPointer(), 0); 431 // allocate an array 432 Array<Integer> pids = s.allocateArray(NativeTypes.INT32, numPids); 433 // list all the pids into the native array 434 proc_listallpids(pids.elementPointer(), numPids); 435 // convert native array to java array 436 int[] jpids = pids.toArray(num -> new int[num]); 437 // buffer for process name 438 Pointer<Byte> nameBuf = s.allocate(NativeTypes.INT8, NAME_BUF_MAX); 439 for (int i = 0; i < jpids.length; i++) { 440 int pid = jpids[i]; 441 // get the process name 442 proc_name(pid, nameBuf, NAME_BUF_MAX); 443 String procName = Pointer.toString(nameBuf); 444 // print pid and process name 445 System.out.printf("%d %s\n", pid, procName); 446 } 447 } 448 } 449 } 450 451 ``` 452 453 ### Running the Java code that uses libproc 454 455 ```sh 456 457 javac -cp libproc.jar LibprocMain.java 458 459 java -cp libproc.jar:. LibprocMain 460 461 ``` 462 463 ## Using readline library from Java code (Mac OS) 464 465 ### jextract a jar file for readline.h 466 467 ```sh 468 469 jextract -l readline -rpath /usr/local/opt/readline/lib/ \ 470 -t org.unix \ 471 /usr/include/readline/readline.h /usr/include/_stdio.h \ 472 --exclude-symbol readline_echoing_p -o readline.jar 473 474 ``` 475 476 ### Java code that uses readline 477 478 ```java 479 480 import java.foreign.*; 481 import java.foreign.memory.*; 482 import static org.unix.readline_h.*; 483 484 public class Readline { 485 public static void main(String[] args) { 486 // Scope for native allocations 487 try (Scope s = Scope.newNativeScope()) { 488 // allocate C memory initialized with Java string content 489 var pstr = s.allocateCString("name? "); 490 491 // call "readline" API 492 var p = readline(pstr); 493 494 // print char* as is 495 System.out.println(p); 496 // convert char* ptr from readline as Java String & print it 497 System.out.println(Pointer.toString(p)); 498 } 499 } 500 } 501 502 ``` 503 504 ### Running the java code that uses readline 505 506 ``` 507 508 javac -cp readline.jar Readline.java 509 510 java -cp readline.jar:. Readline 511 512 ``` 513 514 ## Using unistd.h from Java code (Linux) 515 516 ### jextract a jar file for unistd.h 517 518 ```sh 519 520 jextract /usr/include/unistd.h -t org.unix -o unistd.jar 521 522 ``` 523 524 ### Java code that calls getpid 525 526 ```java 527 528 import java.foreign.*; 529 import java.lang.invoke.*; 530 import org.unix.unistd; 531 532 533 public class Getpid { 534 public static void main(String[] args) { 535 // bind unistd interface 536 var u = Libraries.bind(MethodHandles.lookup(), unistd.class); 537 // call getpid from the unistd.h 538 System.out.println(u.getpid()); 539 // check process id from Java API! 540 System.out.println(ProcessHandle.current().pid()); 541 } 542 } 543 544 ``` 545 546 ### Running the Java code that uses getpid 547 548 ```sh 549 550 javac -cp unistd.jar Getpid.java 551 552 java -cp unistd.jar:. Getpid 553 554 ``` 555 556 557 ## Using OpenGL graphic library (Ubuntu 16.04) 558 559 OpenGL is a popular portable graphic library: [https://www.opengl.org/](https://www.opengl.org/) 560 561 ### Installing OpenGL (Ubuntu 16.04) 562 563 Installing relevant OpenGL headers and libraries can be a bit tricky, as it depends on what graphic card is installed on the target platform. The following instruction assume that the standard version of OpenGL is used (e.g. mesa), rather than a proprietary one (Nvidia or AMD), although the changes to get these working are rather small. 564 565 OpenGL is always coupled with a bunch of other libraries, namely GLU and glut. You can install all those libraries using `apt`, as follows: 566 567 ```sh 568 569 sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev 570 571 ``` 572 573 If the installation was successful, OpenGL headers can be found under `/usr/include/GL`, while libraries can be found in the folder `/usr/lib/x86_64-linux-gnu/`. 574 575 ### jextracting OpenGL (Ubuntu 16.04) 576 577 To extract the opengl libraries the following command suffices: 578 579 ```sh 580 581 jextract -L /usr/lib/x86_64-linux-gnu -l glut -l GLU -l GL --infer-rpath -t opengl -o opengl.jar /usr/include/GL/glut.h 582 583 ``` 584 585 Since glut depends on the other libraries (GLU and GL), it is not necessary to give additional headers to jextract. 586 587 ### Java sample code that uses the OpenGL library 588 589 ```java 590 import java.foreign.Libraries; 591 import java.foreign.NativeTypes; 592 import java.foreign.Scope; 593 import java.foreign.memory.Array; 594 import java.foreign.memory.Pointer; 595 import java.lang.invoke.MethodHandles; 596 597 import opengl.*; 598 599 import javax.imageio.ImageIO; 600 601 public class Teapot { 602 static gl gl = Libraries.bind(MethodHandles.lookup(), gl.class); 603 static freeglut_std glut = Libraries.bind(MethodHandles.lookup(), freeglut_std.class); 604 605 float rot = 0; 606 607 Teapot(Scope sc) { 608 // Misc Parameters 609 Array<Float> pos = sc.allocateArray(NativeTypes.FLOAT, new float[] {0.0f, 15.0f, -15.0f, 0}); 610 Array<Float> spec = sc.allocateArray(NativeTypes.FLOAT, new float[] {1, 1, 1, 0}); 611 Array<Float> shini = sc.allocateArray(NativeTypes.FLOAT, new float[] {113}); 612 613 // Reset Background 614 gl.glClearColor(0, 0, 0, 0); 615 616 // Setup Lighting 617 gl.glShadeModel(gl.GL_SMOOTH()); 618 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_POSITION(), pos.elementPointer()); 619 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_AMBIENT(), spec.elementPointer()); 620 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_DIFFUSE(), spec.elementPointer()); 621 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_SPECULAR(), spec.elementPointer()); 622 gl.glMaterialfv(gl.GL_FRONT(), gl.GL_SHININESS(), shini.elementPointer()); 623 gl.glEnable(gl.GL_LIGHTING()); 624 gl.glEnable(gl.GL_LIGHT0()); 625 gl.glEnable(gl.GL_DEPTH_TEST()); 626 } 627 628 void display() { 629 gl.glClear(gl.GL_COLOR_BUFFER_BIT() | gl.GL_DEPTH_BUFFER_BIT()); 630 gl.glPushMatrix(); 631 gl.glRotatef(-20, 1, 1, 0); 632 gl.glRotatef(rot, 0, 1, 0); 633 glut.glutSolidTeapot(0.5); 634 gl.glPopMatrix(); 635 glut.glutSwapBuffers(); 636 } 637 638 void onIdle() { 639 rot += 0.1; 640 glut.glutPostRedisplay(); 641 } 642 643 public static void main(String[] args) { 644 try (Scope sc = Scope.newNativeScope()) { 645 Pointer<Integer> argc = sc.allocate(NativeTypes.INT32); 646 argc.set(0); 647 glut.glutInit(argc, Pointer.nullPointer()); 648 glut.glutInitDisplayMode(glut.GLUT_DOUBLE() | glut.GLUT_RGBA() | glut.GLUT_DEPTH()); 649 glut.glutInitWindowSize(900, 900); 650 glut.glutCreateWindow(sc.allocateCString("Hello Panama!")); 651 Teapot teapot = new Teapot(sc); 652 glut.glutDisplayFunc(sc.allocateCallback(teapot::display)); 653 glut.glutIdleFunc(sc.allocateCallback(teapot::onIdle)); 654 glut.glutMainLoop(); 655 } 656 } 657 } 658 ``` 659 ### Running the Java code that uses OpenGL 660 661 ```sh 662 663 javac -cp opengl.jar Teapot.java 664 665 java -cp opengl.jar:. Teapot 666 667 ``` 668 669 670 ## Using TensorFlow C API (Mac OS) 671 672 Quoted from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c) 673 674 "TensorFlow provides a C API that can be used to build bindings for other 675 languages. The API is defined in c_api.h and designed for simplicity and 676 uniformity rather than convenience." 677 678 679 ### Installing libtensorflow 680 681 You can follow the setup procedure as described in the above page. 682 683 Alternatively, on Mac, you can install libtensorflow using HomeBrew 684 685 ```sh 686 687 brew install libtensorflow 688 689 ``` 690 691 Tensorflow ship the libtensorflow with an .so extension, this doesn't work 692 well for java on MacOS as java expect .dylib extension. To work around this, 693 create a symbolic link. 694 695 ```sh 696 697 sudo ln -s /usr/local/lib/libtensorflow.so /usr/local/lib/libtensorflow.dylib 698 699 ``` 700 701 ### jextracting libtensorflow c_api.h 702 703 The following command can be used to extract c_api.h. 704 705 ```sh 706 707 jextract -C -x -C c++ \ 708 -L /usr/local/lib -l tensorflow -infer-rpath \ 709 -o tf.jar -t org.tensorflow.panama \ 710 /usr/local/include/tensorflow/c/c_api.h 711 712 ``` 713 714 The caveat to extract tensorflow C API is that it declare function prototype 715 without argument in C++ style, for example, TF_Version(), which is considered 716 incomplete C function prototype instead of C style as in TF_Version(void). An 717 incomplete function prototype will become vararg funciton. To avoid that, we 718 need to pass clang '-x c++' options to jextract with '-C -x -C c++' 719 720 721 ### Java sample code that uses tensorflow library 722 723 ```java 724 725 import java.foreign.NativeTypes; 726 import java.foreign.Scope; 727 import java.foreign.memory.Array; 728 import java.foreign.memory.LayoutType; 729 import java.foreign.memory.Pointer; 730 import org.tensorflow.panama.c_api.TF_DataType; 731 import org.tensorflow.panama.c_api.TF_Graph; 732 import org.tensorflow.panama.c_api.TF_Operation; 733 import org.tensorflow.panama.c_api.TF_OperationDescription; 734 import org.tensorflow.panama.c_api.TF_Output; 735 import org.tensorflow.panama.c_api.TF_Session; 736 import org.tensorflow.panama.c_api.TF_SessionOptions; 737 import org.tensorflow.panama.c_api.TF_Status; 738 import org.tensorflow.panama.c_api.TF_Tensor; 739 740 import static org.tensorflow.panama.c_api_h.*; 741 742 public class TensorFlowExample { 743 static Pointer<TF_Operation> PlaceHolder(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 744 @TF_DataType int dtype, String name) { 745 try (var s = Scope.newNativeScope()) { 746 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 747 s.allocateCString("Placeholder"), s.allocateCString(name)); 748 TF_SetAttrType(desc, s.allocateCString("dtype"), TF_FLOAT); 749 return TF_FinishOperation(desc, status); 750 } 751 } 752 753 static Pointer<TF_Operation> ConstValue(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 754 Pointer<TF_Tensor> tensor, String name) { 755 try (var s = Scope.newNativeScope()) { 756 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 757 s.allocateCString("Const"), s.allocateCString(name)); 758 TF_SetAttrTensor(desc, s.allocateCString("value"), tensor, status); 759 TF_SetAttrType(desc, s.allocateCString("dtype"), TF_TensorType(tensor)); 760 return TF_FinishOperation(desc, status); 761 } 762 } 763 764 static Pointer<TF_Operation> Add(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 765 Pointer<TF_Operation> one, Pointer<TF_Operation> two, 766 String name) { 767 try (var s = Scope.newNativeScope()) { 768 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 769 s.allocateCString("AddN"), s.allocateCString(name)); 770 Array<TF_Output> add_inputs = s.allocateArray( 771 LayoutType.ofStruct(TF_Output.class),2); 772 add_inputs.get(0).oper$set(one); 773 add_inputs.get(0).index$set(0); 774 add_inputs.get(1).oper$set(two); 775 add_inputs.get(1).index$set(0); 776 TF_AddInputList(desc, add_inputs.elementPointer(), 2); 777 return TF_FinishOperation(desc, status); 778 } 779 } 780 781 public static void main(String... args) { 782 System.out.println("TensorFlow C library version: " + Pointer.toString(TF_Version())); 783 784 Pointer<TF_Graph> graph = TF_NewGraph(); 785 Pointer<TF_SessionOptions> options = TF_NewSessionOptions(); 786 Pointer<TF_Status> status = TF_NewStatus(); 787 Pointer<TF_Session> session = TF_NewSession(graph, options, status); 788 789 float in_val_one = 4.0f; 790 float const_two = 2.0f; 791 792 Pointer<TF_Tensor> tensor_in = TF_AllocateTensor(TF_FLOAT, Pointer.nullPointer(), 0, Float.BYTES); 793 TF_TensorData(tensor_in).cast(NativeTypes.FLOAT).set(in_val_one); 794 Pointer<TF_Tensor> tensor_const_two = TF_AllocateTensor(TF_FLOAT, Pointer.nullPointer(), 0, Float.BYTES); 795 TF_TensorData(tensor_const_two).cast(NativeTypes.FLOAT).set(const_two); 796 797 // Operations 798 Pointer<TF_Operation> feed = PlaceHolder(graph, status, TF_FLOAT, "feed"); 799 Pointer<TF_Operation> two = ConstValue(graph, status, tensor_const_two, "const"); 800 Pointer<TF_Operation> add = Add(graph, status, feed, two, "add"); 801 802 803 try (var s = Scope.newNativeScope()) { 804 var ltPtrTensor = LayoutType.ofStruct(TF_Tensor.class).pointer(); 805 806 // Session Inputs 807 TF_Output input_operations = s.allocateStruct(TF_Output.class); 808 input_operations.oper$set(feed); 809 input_operations.index$set(0); 810 Pointer<Pointer<TF_Tensor>> input_tensors = s.allocate(ltPtrTensor); 811 input_tensors.set(tensor_in); 812 813 // Session Outputs 814 TF_Output output_operations = s.allocateStruct(TF_Output.class); 815 output_operations.oper$set(add); 816 output_operations.index$set(0); 817 Pointer<Pointer<TF_Tensor>> output_tensors = s.allocate(ltPtrTensor); 818 TF_SessionRun(session, Pointer.nullPointer(), 819 // Inputs 820 input_operations.ptr(), input_tensors, 1, 821 // Outputs 822 output_operations.ptr(), output_tensors, 1, 823 // Target operations 824 Pointer.nullPointer(), 0, Pointer.nullPointer(), 825 status); 826 827 System.out.println(String.format("Session Run Status: %d - %s", 828 TF_GetCode(status), Pointer.toString(TF_Message(status)))); 829 Pointer<TF_Tensor> tensor_out = output_tensors.get(); 830 System.out.println("Output Tensor Type: " + TF_TensorType(tensor_out)); 831 float outval = TF_TensorData(tensor_out).cast(NativeTypes.FLOAT).get(); 832 System.out.println("Output Tensor Value: " + outval); 833 834 TF_CloseSession(session, status); 835 TF_DeleteSession(session, status); 836 837 TF_DeleteSessionOptions(options); 838 839 TF_DeleteGraph(graph); 840 841 TF_DeleteTensor(tensor_in); 842 TF_DeleteTensor(tensor_out); 843 TF_DeleteTensor(tensor_const_two); 844 845 TF_DeleteStatus(status); 846 } 847 } 848 } 849 850 ``` 851 852 ### Compiling and running the above TensorFlow sample 853 854 ```sh 855 856 javac -cp tf.jar TensorFlowExample.java 857 858 java -cp tf.jar:. TensorFlowExample 859 860 ```