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/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/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 ### Note: This sample fails because of too big UTF-8 String in NativeHeader annotation 466 467 ### jextract a jar file for readline.h 468 469 ```sh 470 471 jextract -l readline -rpath /usr/local/opt/readline/lib/ \ 472 -t org.unix \ 473 /usr/include/readline/readline.h \ 474 --exclude-symbol readline_echoing_p -o readline.jar 475 476 ``` 477 478 ### Java code that uses readline 479 480 ```java 481 482 import java.foreign.*; 483 import java.foreign.memory.*; 484 import static org.unix.readline_h.*; 485 486 public class Readline { 487 public static void main(String[] args) { 488 // Scope for native allocations 489 try (Scope s = Scope.newNativeScope()) { 490 // allocate C memory initialized with Java string content 491 var pstr = s.allocateCString("name? "); 492 493 // call "readline" API 494 var p = readline(pstr); 495 496 // print char* as is 497 System.out.println(p); 498 // convert char* ptr from readline as Java String & print it 499 System.out.println(Pointer.toString(p)); 500 } 501 } 502 } 503 504 ``` 505 506 ### Running the java code that uses readline 507 508 ``` 509 510 javac -cp readline.jar Readline.java 511 512 java -cp readline.jar:. Readline 513 514 ``` 515 516 ## Using unistd.h from Java code (Linux) 517 518 ### jextract a jar file for unistd.h 519 520 ```sh 521 522 jextract /usr/include/unistd.h -t org.unix -o unistd.jar 523 524 ``` 525 526 ### Java code that calls getpid 527 528 ```java 529 530 import java.foreign.*; 531 import java.lang.invoke.*; 532 import org.unix.unistd; 533 534 535 public class Getpid { 536 public static void main(String[] args) { 537 // bind unistd interface 538 var u = Libraries.bind(MethodHandles.lookup(), unistd.class); 539 // call getpid from the unistd.h 540 System.out.println(u.getpid()); 541 // check process id from Java API! 542 System.out.println(ProcessHandle.current().pid()); 543 } 544 } 545 546 ``` 547 548 ### Running the Java code that uses getpid 549 550 ```sh 551 552 javac -cp unistd.jar Getpid.java 553 554 java -cp unistd.jar:. Getpid 555 556 ``` 557 558 559 ## Using OpenGL graphic library (Ubuntu 16.04) 560 561 OpenGL is a popular portable graphic library: [https://www.opengl.org/](https://www.opengl.org/) 562 563 ### Installing OpenGL (Ubuntu 16.04) 564 565 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. 566 567 OpenGL is always coupled with a bunch of other libraries, namely GLU and glut. You can install all those libraries using `apt`, as follows: 568 569 ```sh 570 571 sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev 572 573 ``` 574 575 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/`. 576 577 ### jextracting OpenGL (Ubuntu 16.04) 578 579 To extract the opengl libraries the following command suffices: 580 581 ```sh 582 583 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 584 585 ``` 586 587 Since glut depends on the other libraries (GLU and GL), it is not necessary to give additional headers to jextract. 588 589 ### Java sample code that uses the OpenGL library 590 591 ```java 592 import java.foreign.Libraries; 593 import java.foreign.NativeTypes; 594 import java.foreign.Scope; 595 import java.foreign.memory.Array; 596 import java.foreign.memory.Pointer; 597 import java.lang.invoke.MethodHandles; 598 599 import opengl.*; 600 601 import javax.imageio.ImageIO; 602 603 public class Teapot { 604 static gl gl = Libraries.bind(MethodHandles.lookup(), gl.class); 605 static freeglut_std glut = Libraries.bind(MethodHandles.lookup(), freeglut_std.class); 606 607 float rot = 0; 608 609 Teapot(Scope sc) { 610 // Misc Parameters 611 Array<Float> pos = sc.allocateArray(NativeTypes.FLOAT, new float[] {0.0f, 15.0f, -15.0f, 0}); 612 Array<Float> spec = sc.allocateArray(NativeTypes.FLOAT, new float[] {1, 1, 1, 0}); 613 Array<Float> shini = sc.allocateArray(NativeTypes.FLOAT, new float[] {113}); 614 615 // Reset Background 616 gl.glClearColor(0, 0, 0, 0); 617 618 // Setup Lighting 619 gl.glShadeModel(gl.GL_SMOOTH()); 620 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_POSITION(), pos.elementPointer()); 621 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_AMBIENT(), spec.elementPointer()); 622 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_DIFFUSE(), spec.elementPointer()); 623 gl.glLightfv(gl.GL_LIGHT0(), gl.GL_SPECULAR(), spec.elementPointer()); 624 gl.glMaterialfv(gl.GL_FRONT(), gl.GL_SHININESS(), shini.elementPointer()); 625 gl.glEnable(gl.GL_LIGHTING()); 626 gl.glEnable(gl.GL_LIGHT0()); 627 gl.glEnable(gl.GL_DEPTH_TEST()); 628 } 629 630 void display() { 631 gl.glClear(gl.GL_COLOR_BUFFER_BIT() | gl.GL_DEPTH_BUFFER_BIT()); 632 gl.glPushMatrix(); 633 gl.glRotatef(-20, 1, 1, 0); 634 gl.glRotatef(rot, 0, 1, 0); 635 glut.glutSolidTeapot(0.5); 636 gl.glPopMatrix(); 637 glut.glutSwapBuffers(); 638 } 639 640 void onIdle() { 641 rot += 0.1; 642 glut.glutPostRedisplay(); 643 } 644 645 public static void main(String[] args) { 646 try (Scope sc = Scope.newNativeScope()) { 647 Pointer<Integer> argc = sc.allocate(NativeTypes.INT32); 648 argc.set(0); 649 glut.glutInit(argc, Pointer.nullPointer()); 650 glut.glutInitDisplayMode(glut.GLUT_DOUBLE() | glut.GLUT_RGBA() | glut.GLUT_DEPTH()); 651 glut.glutInitWindowSize(900, 900); 652 glut.glutCreateWindow(sc.allocateCString("Hello Panama!")); 653 Teapot teapot = new Teapot(sc); 654 glut.glutDisplayFunc(sc.allocateCallback(teapot::display)); 655 glut.glutIdleFunc(sc.allocateCallback(teapot::onIdle)); 656 glut.glutMainLoop(); 657 } 658 } 659 } 660 ``` 661 ### Running the Java code that uses OpenGL 662 663 ```sh 664 665 javac -cp opengl.jar Teapot.java 666 667 java -cp opengl.jar:. Teapot 668 669 ``` 670 671 672 ## Using TensorFlow C API (Mac OS) 673 674 Quoted from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c) 675 676 "TensorFlow provides a C API that can be used to build bindings for other 677 languages. The API is defined in c_api.h and designed for simplicity and 678 uniformity rather than convenience." 679 680 681 ### Installing libtensorflow 682 683 You can follow the setup procedure as described in the above page. 684 685 Alternatively, on Mac, you can install libtensorflow using HomeBrew 686 687 ```sh 688 689 brew install libtensorflow 690 691 ``` 692 693 Tensorflow ship the libtensorflow with an .so extension, this doesn't work 694 well for java on MacOS as java expect .dylib extension. To work around this, 695 create a symbolic link. 696 697 ```sh 698 699 sudo ln -s /usr/local/lib/libtensorflow.so /usr/local/lib/libtensorflow.dylib 700 701 ``` 702 703 ### jextracting libtensorflow c_api.h 704 705 The following command can be used to extract c_api.h. 706 707 ```sh 708 709 jextract -C -x -C c++ \ 710 -L /usr/local/lib -l tensorflow -infer-rpath \ 711 -o tf.jar -t org.tensorflow.panama \ 712 /usr/local/include/tensorflow/c/c_api.h 713 714 ``` 715 716 The caveat to extract tensorflow C API is that it declare function prototype 717 without argument in C++ style, for example, TF_Version(), which is considered 718 incomplete C function prototype instead of C style as in TF_Version(void). An 719 incomplete function prototype will become vararg funciton. To avoid that, we 720 need to pass clang '-x c++' options to jextract with '-C -x -C c++' 721 722 723 ### Java sample code that uses tensorflow library 724 725 ```java 726 727 import java.foreign.NativeTypes; 728 import java.foreign.Scope; 729 import java.foreign.memory.Array; 730 import java.foreign.memory.LayoutType; 731 import java.foreign.memory.Pointer; 732 import org.tensorflow.panama.c_api.TF_DataType; 733 import org.tensorflow.panama.c_api.TF_Graph; 734 import org.tensorflow.panama.c_api.TF_Operation; 735 import org.tensorflow.panama.c_api.TF_OperationDescription; 736 import org.tensorflow.panama.c_api.TF_Output; 737 import org.tensorflow.panama.c_api.TF_Session; 738 import org.tensorflow.panama.c_api.TF_SessionOptions; 739 import org.tensorflow.panama.c_api.TF_Status; 740 import org.tensorflow.panama.c_api.TF_Tensor; 741 742 import static org.tensorflow.panama.c_api_h.*; 743 744 public class TensorFlowExample { 745 static Pointer<TF_Operation> PlaceHolder(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 746 @TF_DataType int dtype, String name) { 747 try (var s = Scope.newNativeScope()) { 748 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 749 s.allocateCString("Placeholder"), s.allocateCString(name)); 750 TF_SetAttrType(desc, s.allocateCString("dtype"), TF_FLOAT); 751 return TF_FinishOperation(desc, status); 752 } 753 } 754 755 static Pointer<TF_Operation> ConstValue(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 756 Pointer<TF_Tensor> tensor, String name) { 757 try (var s = Scope.newNativeScope()) { 758 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 759 s.allocateCString("Const"), s.allocateCString(name)); 760 TF_SetAttrTensor(desc, s.allocateCString("value"), tensor, status); 761 TF_SetAttrType(desc, s.allocateCString("dtype"), TF_TensorType(tensor)); 762 return TF_FinishOperation(desc, status); 763 } 764 } 765 766 static Pointer<TF_Operation> Add(Pointer<TF_Graph> graph, Pointer<TF_Status> status, 767 Pointer<TF_Operation> one, Pointer<TF_Operation> two, 768 String name) { 769 try (var s = Scope.newNativeScope()) { 770 Pointer<TF_OperationDescription> desc = TF_NewOperation(graph, 771 s.allocateCString("AddN"), s.allocateCString(name)); 772 Array<TF_Output> add_inputs = s.allocateArray( 773 LayoutType.ofStruct(TF_Output.class),2); 774 add_inputs.get(0).oper$set(one); 775 add_inputs.get(0).index$set(0); 776 add_inputs.get(1).oper$set(two); 777 add_inputs.get(1).index$set(0); 778 TF_AddInputList(desc, add_inputs.elementPointer(), 2); 779 return TF_FinishOperation(desc, status); 780 } 781 } 782 783 public static void main(String... args) { 784 System.out.println("TensorFlow C library version: " + Pointer.toString(TF_Version())); 785 786 Pointer<TF_Graph> graph = TF_NewGraph(); 787 Pointer<TF_SessionOptions> options = TF_NewSessionOptions(); 788 Pointer<TF_Status> status = TF_NewStatus(); 789 Pointer<TF_Session> session = TF_NewSession(graph, options, status); 790 791 float in_val_one = 4.0f; 792 float const_two = 2.0f; 793 794 Pointer<TF_Tensor> tensor_in = TF_AllocateTensor(TF_FLOAT, Pointer.nullPointer(), 0, Float.BYTES); 795 TF_TensorData(tensor_in).cast(NativeTypes.FLOAT).set(in_val_one); 796 Pointer<TF_Tensor> tensor_const_two = TF_AllocateTensor(TF_FLOAT, Pointer.nullPointer(), 0, Float.BYTES); 797 TF_TensorData(tensor_const_two).cast(NativeTypes.FLOAT).set(const_two); 798 799 // Operations 800 Pointer<TF_Operation> feed = PlaceHolder(graph, status, TF_FLOAT, "feed"); 801 Pointer<TF_Operation> two = ConstValue(graph, status, tensor_const_two, "const"); 802 Pointer<TF_Operation> add = Add(graph, status, feed, two, "add"); 803 804 805 try (var s = Scope.newNativeScope()) { 806 var ltPtrTensor = LayoutType.ofStruct(TF_Tensor.class).pointer(); 807 808 // Session Inputs 809 TF_Output input_operations = s.allocateStruct(TF_Output.class); 810 input_operations.oper$set(feed); 811 input_operations.index$set(0); 812 Pointer<Pointer<TF_Tensor>> input_tensors = s.allocate(ltPtrTensor); 813 input_tensors.set(tensor_in); 814 815 // Session Outputs 816 TF_Output output_operations = s.allocateStruct(TF_Output.class); 817 output_operations.oper$set(add); 818 output_operations.index$set(0); 819 Pointer<Pointer<TF_Tensor>> output_tensors = s.allocate(ltPtrTensor); 820 TF_SessionRun(session, Pointer.nullPointer(), 821 // Inputs 822 input_operations.ptr(), input_tensors, 1, 823 // Outputs 824 output_operations.ptr(), output_tensors, 1, 825 // Target operations 826 Pointer.nullPointer(), 0, Pointer.nullPointer(), 827 status); 828 829 System.out.println(String.format("Session Run Status: %d - %s", 830 TF_GetCode(status), Pointer.toString(TF_Message(status)))); 831 Pointer<TF_Tensor> tensor_out = output_tensors.get(); 832 System.out.println("Output Tensor Type: " + TF_TensorType(tensor_out)); 833 float outval = TF_TensorData(tensor_out).cast(NativeTypes.FLOAT).get(); 834 System.out.println("Output Tensor Value: " + outval); 835 836 TF_CloseSession(session, status); 837 TF_DeleteSession(session, status); 838 839 TF_DeleteSessionOptions(options); 840 841 TF_DeleteGraph(graph); 842 843 TF_DeleteTensor(tensor_in); 844 TF_DeleteTensor(tensor_out); 845 TF_DeleteTensor(tensor_const_two); 846 847 TF_DeleteStatus(status); 848 } 849 } 850 } 851 852 ``` 853 854 ### Compiling and running the above TensorFlow sample 855 856 ```sh 857 858 javac -cp tf.jar TensorFlowExample.java 859 860 java -cp tf.jar:. TensorFlowExample 861 862 ``` --- EOF ---