1 % Using Panama "foreign" JDK
   2 
   3 <?xml version="1.0" encoding="utf-8"?>
   4 
   5 # Using Panama "foreign" JDK
   6 
   7 There are two ways to get a panama foreign branch JDK.
   8 
   9 1. Locally build "foreign" branch of panama repo [http://hg.openjdk.java.net/panama/dev/](http://hg.openjdk.java.net/panama/dev/)
  10 2. Download pre-built panama "foreign" early access binaries from [http://jdk.java.net/panama/](http://jdk.java.net/panama/)
  11 
  12 Using foreign function call in Java involves the following three steps:
  13 
  14 1. Use **jextract** tool to generate java interface for your C header file(s)
  15 2. Use **java.foreign** API to create ("bind") implementation for C header interfaces
  16 3. Invoke C functions via the jextracted Java interface
  17 
  18 ### Windows notes
  19 
  20 You will (almost always) need to have Visual Studio installed, since most libraries indirectly depend on Visual Studio runtime libraries and this currently means that jextract needs their header to extract successfully. Windows examples have been tested with [Build Tools for Visual Studio 2017](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2017).
  21 
  22 It is generally a good idea to give jextract a bunch of extra memory since a lot of big system headers are transitively included. The extra memory will make the jextract run significantly faster. Windows support was added only recently, and the memory usage of jextract has not been optimized yet, so this is a workaround. You can give extra memory by passing e.g. `-J-Xmx8G` to jextract as an additional argument, which in this example gives jextract 8 gigabytes of memory.
  23 
  24 Commands are tested in PowerShell.
  25 
  26 ## Hello World
  27 
  28 ### Hello World C Header
  29 
  30 ```C
  31 
  32 #ifndef helloworld_h
  33 #define helloworld_h
  34 
  35 extern void helloworld(void);
  36 
  37 ```
  38 
  39 ### Hello World C Source
  40 
  41 ```C
  42 
  43 #include <stdio.h>
  44 
  45 #include "helloworld.h"
  46 
  47 void helloworld(void) {
  48     printf("Hello World!\n");
  49 }
  50 
  51 ```
  52 
  53 ### jextract a Jar file for helloworld.h
  54 
  55 ```sh
  56 
  57 jextract -t org.hello -L . -lhelloworld --record-library-path helloworld.h -o helloworld.jar
  58 
  59 ```
  60 
  61 ### Java program that uses extracted helloworld interface
  62 
  63 ```java
  64 
  65 import org.hello.helloworld_lib;
  66 
  67 import static org.hello.helloworld_lib.*;
  68 
  69 public class HelloWorld {
  70     public static void main(String[] args) {
  71         try (Scope s = helloworld_lib.scope().fork()) {
  72             helloworld();
  73         }
  74     }
  75 }
  76 
  77 ```
  78 
  79 ### Running the Java code that invokes helloworld
  80 
  81 ```sh
  82 
  83 javac -cp helloworld.jar HelloWorld.java
  84 
  85 java -cp helloworld.jar:. HelloWorld
  86 
  87 ```
  88 
  89 ## Embedding Python interpreter in your Java program (Mac OS)
  90 
  91 ### jextract a Jar file for Python.h
  92 
  93 ```sh
  94 
  95 jextract -l python2.7 \
  96   -L /System/Library/Frameworks/Python.framework/Versions/2.7/lib --record-library-path \
  97   --exclude-symbols .*_FromFormatV\|_.*\|PyOS_vsnprintf\|.*_VaParse.*\|.*_VaBuild.*\|PyBuffer_SizeFromFormat\|vasprintf\|vfprintf\|vprintf\|vsprintf \
  98   -t org.python \
  99   /usr/include/python2.7/Python.h \
 100   -o python.jar
 101 
 102 ```
 103 
 104 ### Java program that uses extracted Python interface
 105 
 106 ```java
 107 
 108 // import java.foreign packages
 109 import java.foreign.Libraries;
 110 import java.foreign.Scope;
 111 import java.foreign.memory.Pointer;
 112 
 113 // import jextracted python 'header' classes
 114 import static org.python.Python_lib.*;
 115 import static org.python.pythonrun_lib.*;
 116 
 117 public class PythonMain {
 118     public static void main(String[] args) {
 119         Py_Initialize();
 120         try (Scope s = org.python.Python_lib.scope().fork()) {
 121             PyRun_SimpleStringFlags(s.allocateCString(
 122                 "print(sum([33, 55, 66])); print('Hello from Python!')\n"),
 123                 Pointer.ofNull());
 124         }
 125         Py_Finalize();
 126     }
 127 }
 128 
 129 ```
 130 
 131 ### Running the Java code that calls Python interpreter
 132 
 133 ```sh
 134 
 135 javac -cp python.jar PythonMain.java
 136 
 137 java -cp python.jar:. PythonMain
 138 
 139 ```
 140 
 141 ## jlinking Python Interpreter in your JDK (Mac OS)
 142 
 143 ### Generating jmod using jextract
 144 
 145 ```sh
 146 
 147 jextract -l python2.7 \
 148   -L /System/Library/Frameworks/Python.framework/Versions/2.7/lib \
 149   --exclude-symbols .*_FromFormatV\|_.*\|PyOS_vsnprintf\|.*_VaParse.*\|.*_VaBuild.*\|PyBuffer_SizeFromFormat\|vasprintf\|vfprintf\|vprintf\|vsprintf \
 150   -t org.python \
 151   /usr/include/python2.7/Python.h \
 152   -o org.python.jmod
 153 
 154 ```
 155 
 156 ### Jlinking python module to create a JDK with Python in it
 157 
 158 jdk.compiler and org.python modules are added to the generated (jlinked) JDK
 159 
 160 ```sh
 161 
 162 jlink --add-modules org.python,jdk.compiler --module-path . --output pythonjdk
 163 
 164 ```
 165 
 166 ### Compile and run user code with "pythonjdk" jdk
 167 
 168 In the following commands, it is assumed that you've put $pythonjdk/bin in your $PATH
 169 
 170 ```sh
 171 
 172 javac PythonMain.java
 173 java PythonMain
 174 
 175 ```
 176 
 177 ## Embedding Python interpreter in your Java program (Ubuntu 16.04)
 178 
 179 ### jextract a Jar file for Python.h
 180 
 181 ```sh
 182 
 183 jextract -l python2.7 \
 184   -L /usr/lib/python2.7/config-x86_64-linux-gnu --record-library-path \
 185   --exclude-symbols .*_FromFormatV\|_.*\|PyOS_vsnprintf\|.*_VaParse.*\|.*_VaBuild.*\|PyBuffer_SizeFromFormat\|vasprintf\|vfprintf\|vprintf\|vsprintf \
 186   -t org.python \
 187   /usr/include/python2.7/Python.h \
 188   -o python.jar
 189 
 190 ```
 191 
 192 ### Compiling and Running Python Java example
 193 
 194 Follow the instructions from the Mac OS section
 195 
 196 ## Embedding Python interpreter in your Java program (Windows)
 197 
 198 ### jextract a Jar file for Python.h
 199 
 200 Where python 2.7 is installed in the `C:\Python27` directory:
 201 
 202 ```powershell
 203 jextract -L "C:\Windows\System32" -l python27 -o python.jar -t "org.python" --record-library-path C:\Python27\include\Python.h
 204 ```
 205 
 206 ### Compiling and Running Python Java example
 207 
 208 ```powershell
 209 javac -cp python.jar PythonMain.java
 210 java -cp "python.jar;." PythonMain
 211 ```
 212 
 213 ## Using sqlite3 library in your Java program (Mac OS)
 214 
 215 ### jextract a jar file for sqlite3.h
 216 
 217 ```sh
 218 
 219 jextract  /usr/include/sqlite3.h -t org.sqlite -lsqlite3 \
 220     -L /usr/lib --record-library-path         \
 221     --exclude-symbols sqlite3_vmprintf        \
 222     --exclude-symbols sqlite3_vsnprintf       \
 223     -o sqlite3.jar
 224 
 225 ```
 226 
 227 ### Java sample that uses sqlite3 library
 228 
 229 ```java
 230 
 231 import java.lang.invoke.*;
 232 import java.foreign.*;
 233 import java.foreign.memory.*;
 234 import org.sqlite.sqlite3_h.*;
 235 import static org.sqlite.sqlite3_lib.*;
 236 
 237 public class SqliteMain {
 238    public static void main(String[] args) throws Exception {
 239         try (Scope scope = scope().fork()) {
 240             // char* errMsg;
 241             Pointer<Pointer<Byte>> errMsg = scope.allocate(NativeTypes.INT8.pointer());
 242 
 243             // sqlite3* db;
 244             Pointer<Pointer<sqlite3>> db = scope.allocate(LayoutType.ofStruct(sqlite3.class).pointer());
 245 
 246             int rc = sqlite3_open(scope.allocateCString("employee.db"), db);
 247             if (rc != 0) {
 248                 System.err.println("sqlite3_open failed: " + rc);
 249                 return;
 250             }
 251 
 252             // create a new table
 253             Pointer<Byte> sql = scope.allocateCString(
 254                 "CREATE TABLE EMPLOYEE ("  +
 255                 "  ID INT PRIMARY KEY NOT NULL,"       +
 256                 "  NAME TEXT NOT NULL,"    +
 257                 "  SALARY REAL NOT NULL )"
 258             );
 259 
 260             rc = sqlite3_exec(db.get(), sql, Callback.ofNull(), Pointer.ofNull(), errMsg);
 261 
 262             if (rc != 0) {
 263                 System.err.println("sqlite3_exec failed: " + rc);
 264                 System.err.println("SQL error: " + Pointer.toString(errMsg.get()));
 265                 sqlite3_free(errMsg.get());
 266             }
 267 
 268             // insert two rows
 269             sql = scope.allocateCString(
 270                 "INSERT INTO EMPLOYEE (ID,NAME,SALARY) " +
 271                     "VALUES (134, 'Xyz', 200000.0); " +
 272                 "INSERT INTO EMPLOYEE (ID,NAME,SALARY) " +
 273                     "VALUES (333, 'Abc', 100000.0);"
 274             );
 275             rc = sqlite3_exec(db.get(), sql, Callback.ofNull(), Pointer.ofNull(), errMsg);
 276 
 277             if (rc != 0) {
 278                 System.err.println("sqlite3_exec failed: " + rc);
 279                 System.err.println("SQL error: " + Pointer.toString(errMsg.get()));
 280                 sqlite3_free(errMsg.get());
 281             }
 282 
 283             int[] rowNum = new int[1];
 284             // callback to print rows from SELECT query
 285             Callback<FI1> callback = scope.allocateCallback(FI1.class, (a, argc, argv, columnNames) -> {
 286                 System.out.println("Row num: " + rowNum[0]++);
 287                 System.out.println("numColumns = " + argc);
 288                 for (int i = 0; i < argc; i++) {
 289                      String name = Pointer.toString(columnNames.offset(i).get());
 290                      String value = Pointer.toString(argv.offset(i).get());
 291                      System.out.printf("%s = %s\n", name, value);
 292                 }
 293                 return 0;
 294             });
 295 
 296             // select query
 297             sql = scope.allocateCString("SELECT * FROM EMPLOYEE");
 298             rc = sqlite3_exec(db.get(), sql, callback, Pointer.ofNull(), errMsg);
 299 
 300             if (rc != 0) {
 301                 System.err.println("sqlite3_exec failed: " + rc);
 302                 System.err.println("SQL error: " + Pointer.toString(errMsg.get()));
 303                 sqlite3_free(errMsg.get());
 304             }
 305 
 306             sqlite3_close(db.get());
 307         }
 308    }
 309 }
 310 
 311 ```
 312 
 313 ### Compiling and Running sqlite Java example
 314 
 315 ```sh
 316 
 317 javac -cp sqlite3.jar SqlMain.java
 318 java -cp sqlite3.jar:. SqlMain
 319 
 320 ```
 321 
 322 ## Using sqlite3 library in your Java program (Ubuntu 16.04)
 323 
 324 ### Installing sqlite3
 325 
 326 On Ubuntu (16.04) to install sqlite3 headers and libraries the following command is required:
 327 
 328 ```sh
 329 sudo apt-get install libsqlite3-dev
 330 ```
 331 
 332 This should install the sqlite3 header (under `/usr/include`), as well as the sqlite3 shared library (under `/usr/lib/x86_64-linux-gnu`).
 333 
 334 ### jextract a jar file for sqlite3.h
 335 
 336 To extract sqlite, run the following command:
 337 
 338 ```sh
 339 jextract  /usr/include/sqlite3.h -t org.sqlite -lsqlite3 \
 340           -L /usr/lib/x86_64-linux-gnu --record-library-path \
 341            --exclude-symbols sqlite3_vmprintf \
 342            --exclude-symbols sqlite3_vsnprintf \
 343            -o sqlite3.jar
 344 ```
 345 
 346 ### Compiling and Running sqlite Java example
 347 
 348 Please refer to the Mac OS instructions; once the library as been extracted (as per the instructions above), the sample program shown in that section should work on Ubuntu as well.
 349 
 350 ## Using BLAS library
 351 
 352 BLAS is a popular library that allows fast matrix and vector computation: [http://www.netlib.org/blas/](http://www.netlib.org/blas/).
 353 
 354 ### Installing OpenBLAS (Mac OS)
 355 
 356 On Mac, blas is available as part of the OpenBLAS library: [https://github.com/xianyi/OpenBLAS/wiki](https://github.com/xianyi/OpenBLAS/wiki)
 357 
 358 OpenBLAS is an optimized BLAS library based on GotoBLAS2 1.13 BSD version.
 359 
 360 You can install openblas using HomeBrew
 361 
 362 ```sh
 363 
 364 brew install openblas
 365 
 366 ```
 367 
 368 It installs include and lib directories under /usr/local/opt/openblas
 369 
 370 ### Installing OpenBLAS (Ubuntu 16.04)
 371 
 372 On Ubuntu, blas is distributed as part of the atlas library: [http://math-atlas.sourceforge.net/](http://math-atlas.sourceforge.net/).
 373 
 374 You can install atlas using apt
 375 
 376 ```sh
 377 
 378 sudo apt-get install libatlas-base-dev
 379 
 380 ```
 381 
 382 This command will install include files under `/usr/include/atlas` and corresponding libraries under `/usr/lib/atlas-dev`.
 383 
 384 
 385 ### jextracting cblas.h (MacOS)
 386 
 387 The following command can be used to extract cblas.h on MacOs
 388 
 389 ```sh
 390 
 391 jextract -C "-D FORCE_OPENBLAS_COMPLEX_STRUCT" \
 392   -L /usr/local/opt/openblas/lib \
 393   -l openblas -t blas --record-library-path /usr/local/opt/openblas/include/cblas.h \
 394   -o cblas.jar
 395 
 396 ```
 397 
 398 The FORCE_OPENBLAS_COMPLEX_STRUCT define is needed because jextract does not
 399 yet handle C99 `_Complex` types. The rest of the options are standard ones.
 400 
 401 ### jextracting cblas.h (Ubuntu 16.04)
 402 
 403 The following command can be used to extract cblas.h on Ubuntu
 404 
 405 ```sh
 406 
 407 jextract -L /usr/lib/atlas-base -I /usr/include/atlas/ \
 408    -l cblas -t blas --record-library-path \
 409    /usr/include/atlas/cblas.h -o cblas.jar
 410 
 411 ```
 412 
 413 ### Java sample code that uses cblas library
 414 
 415 ```java
 416 
 417 import blas.cblas_h;
 418 import static blas.cblas_lib.*;
 419 import static blas.cblas_lib.CBLAS_ORDER.*;
 420 import static blas.cblas_lib.CBLAS_TRANSPOSE.*;
 421 
 422 import java.foreign.NativeTypes;
 423 import java.foreign.Scope;
 424 import java.foreign.memory.Array;
 425 
 426 public class TestBlas {
 427    public static void main(String[] args) {
 428        @cblas_h.CBLAS_ORDER int Layout;
 429        @cblas_h.CBLAS_TRANSPOSE int transa;
 430 
 431        double alpha, beta;
 432        int m, n, lda, incx, incy, i;
 433 
 434        Layout = CblasColMajor;
 435        transa = CblasNoTrans;
 436 
 437        m = 4; /* Size of Column ( the number of rows ) */
 438        n = 4; /* Size of Row ( the number of columns ) */
 439        lda = 4; /* Leading dimension of 5 * 4 matrix is 5 */
 440        incx = 1;
 441        incy = 1;
 442        alpha = 1;
 443        beta = 0;
 444 
 445        try (Scope sc = scope().fork()){
 446            Array<Double> a = sc.allocateArray(NativeTypes.DOUBLE, m * n);
 447            Array<Double> x = sc.allocateArray(NativeTypes.DOUBLE, n);
 448            Array<Double> y = sc.allocateArray(NativeTypes.DOUBLE, n);
 449            /* The elements of the first column */
 450            a.set(0, 1.0);
 451            a.set(1, 2.0);
 452            a.set(2, 3.0);
 453            a.set(3, 4.0);
 454            /* The elements of the second column */
 455            a.set(m, 1.0);
 456            a.set(m + 1, 1.0);
 457            a.set(m + 2, 1.0);
 458            a.set(m + 3, 1.0);
 459            /* The elements of the third column */
 460            a.set(m * 2, 3.0);
 461            a.set(m * 2 + 1, 4.0);
 462            a.set(m * 2 + 2, 5.0);
 463            a.set(m * 2 + 3, 6.0);
 464            /* The elements of the fourth column */
 465            a.set(m * 3, 5.0);
 466            a.set(m * 3 + 1, 6.0);
 467            a.set(m * 3 + 2, 7.0);
 468            a.set(m * 3 + 3, 8.0);
 469            /* The elemetns of x and y */
 470            x.set(0, 1.0);
 471            x.set(1, 2.0);
 472            x.set(2, 1.0);
 473            x.set(3, 1.0);
 474            y.set(0, 0.0);
 475            y.set(1, 0.0);
 476            y.set(2, 0.0);
 477            y.set(3, 0.0);
 478 
 479            cblas_dgemv(Layout, transa, m, n, alpha, a.elementPointer(), lda, x.elementPointer(), incx, beta,
 480                    y.elementPointer(), incy);
 481            /* Print y */
 482            for (i = 0; i < n; i++)
 483                System.out.print(String.format(" y%d = %f\n", i, y.get(i)));
 484        }
 485    }
 486 }
 487 
 488 ```
 489 
 490 ### Compiling and running the above cblas samples
 491 
 492 ```sh
 493 
 494 javac -cp cblas.jar TestBlas.java
 495 
 496 java -cp cblas.jar:. TestBlas
 497 
 498 ```
 499 
 500 ## Using LAPACK library (Ubuntu)
 501 
 502 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.
 503 
 504 ### jextracting clapack.h (Ubuntu 16.04)
 505 
 506 The following command can be used to extract the LAPACK header:
 507 
 508 ```sh
 509 
 510 jextract -L /usr/lib/atlas-base/atlas -I /usr/include/atlas/ \
 511    -l lapack -t lapack --record-library-path /usr/include/atlas/clapack.h -o clapack.jar
 512 
 513 ```
 514 
 515 ### Java sample code that uses LAPACK library
 516 
 517 ```java
 518 import java.foreign.NativeTypes;
 519 import java.foreign.Scope;
 520 import java.foreign.memory.Array;
 521 
 522 import static lapack.clapack_lib.*;
 523 import static lapack.cblas_lib.*;
 524 
 525 public class TestLapack {
 526     public static void main(String[] args) {
 527 
 528         /* Locals */
 529         try (Scope sc = lapack.clapack_lib.scope().fork()) {
 530             Array<Double> A = sc.allocateArray(NativeTypes.DOUBLE, new double[]{
 531                     1, 2, 3, 4, 5, 1, 3, 5, 2, 4, 1, 4, 2, 5, 3
 532             });
 533             Array<Double> b = sc.allocateArray(NativeTypes.DOUBLE, new double[]{
 534                     -10, 12, 14, 16, 18, -3, 14, 12, 16, 16
 535             });
 536             int info, m, n, lda, ldb, nrhs;
 537 
 538             /* Initialization */
 539             m = 5;
 540             n = 3;
 541             nrhs = 2;
 542             lda = 5;
 543             ldb = 5;
 544 
 545             /* Print Entry Matrix */
 546             print_matrix_colmajor("Entry Matrix A", m, n, A, lda );
 547             /* Print Right Rand Side */
 548             print_matrix_colmajor("Right Hand Side b", n, nrhs, b, ldb );
 549             System.out.println();
 550 
 551             /* Executable statements */
 552             //            printf( "LAPACKE_dgels (col-major, high-level) Example Program Results\n" );
 553             /* Solve least squares problem*/
 554             info = clapack_dgels(CblasColMajor, CblasNoTrans, m, n, nrhs, A.elementPointer(), lda, b.elementPointer(), ldb);
 555 
 556             /* Print Solution */
 557             print_matrix_colmajor("Solution", n, nrhs, b, ldb );
 558             System.out.println();
 559             System.exit(info);
 560         }
 561     }
 562 
 563     static void print_matrix_colmajor(String msg, int m, int n, Array<Double> mat, int ldm) {
 564         int i, j;
 565         System.out.printf("\n %s\n", msg);
 566 
 567         for( i = 0; i < m; i++ ) {
 568             for( j = 0; j < n; j++ ) System.out.printf(" %6.2f", mat.get(i+j*ldm));
 569             System.out.printf( "\n" );
 570         }
 571     }
 572 }
 573 ```
 574 
 575 ### Compiling and running the above LAPACK sample
 576 
 577 ```sh
 578 
 579 javac -cp clapack.jar TestLapack.java
 580 
 581 java -cp clapack.jar:. TestLapack
 582 
 583 ```
 584 
 585 ## Using LAPACK library (Mac OS)
 586 
 587 On Mac OS, lapack is installed under /usr/local/opt/lapack directory.
 588 
 589 ### jextracting lapacke.h
 590 
 591 ```sh
 592 
 593 jextract -L /usr/local/opt/lapack/lib \
 594   -l lapacke -t lapack --record-library-path \
 595   /usr/local/opt/lapack/include/lapacke.h -o clapack.jar
 596 
 597 ```
 598 ### Java sample code that uses LAPACK library
 599 
 600 ```java
 601 
 602 import java.foreign.NativeTypes;
 603 import java.foreign.Scope;
 604 import java.foreign.memory.Array;
 605 
 606 import static lapack.lapacke_lib.*;
 607 
 608 public class TestLapack {
 609     public static void main(String[] args) {
 610 
 611         /* Locals */
 612         try (Scope sc = scope().fork()) {
 613             Array<Double> A = sc.allocateArray(NativeTypes.DOUBLE, new double[]{
 614                     1, 2, 3, 4, 5, 1, 3, 5, 2, 4, 1, 4, 2, 5, 3
 615             });
 616             Array<Double> b = sc.allocateArray(NativeTypes.DOUBLE, new double[]{
 617                     -10, 12, 14, 16, 18, -3, 14, 12, 16, 16
 618             });
 619             int info, m, n, lda, ldb, nrhs;
 620 
 621             /* Initialization */
 622             m = 5;
 623             n = 3;
 624             nrhs = 2;
 625             lda = 5;
 626             ldb = 5;
 627 
 628             /* Print Entry Matrix */
 629             print_matrix_colmajor("Entry Matrix A", m, n, A, lda );
 630             /* Print Right Rand Side */
 631             print_matrix_colmajor("Right Hand Side b", n, nrhs, b, ldb );
 632             System.out.println();
 633 
 634             /* Executable statements */
 635             //            printf( "LAPACKE_dgels (col-major, high-level) Example Program Results\n" );
 636             /* Solve least squares problem*/
 637             info = LAPACKE_dgels(LAPACK_COL_MAJOR, (byte)'N', m, n, nrhs, A.elementPointer(), lda, b.elementPointer(), ldb);
 638 
 639             /* Print Solution */
 640             print_matrix_colmajor("Solution", n, nrhs, b, ldb );
 641             System.out.println();
 642             System.exit(info);
 643         }
 644     }
 645 
 646     static void print_matrix_colmajor(String msg, int m, int n, Array<Double> mat, int ldm) {
 647         int i, j;
 648         System.out.printf("\n %s\n", msg);
 649 
 650         for( i = 0; i < m; i++ ) {
 651             for( j = 0; j < n; j++ ) System.out.printf(" %6.2f", mat.get(i+j*ldm));
 652             System.out.printf( "\n" );
 653         }
 654     }
 655 }
 656 
 657 ```
 658 
 659 ### Compiling and running the above LAPACK sample
 660 
 661 ```sh
 662 
 663 javac -cp clapack.jar TestLapack.java
 664 
 665 java -cp clapack.jar:. TestLapack
 666 
 667 ```
 668 
 669 ## Using libproc library to list processes from Java (Mac OS)
 670 
 671 ### jextract a jar file for libproc.h
 672 
 673 jextract -t org.unix -lproc -L /usr/lib --record-library-path -o libproc.jar /usr/include/libproc.h
 674 
 675 ### Java program that uses libproc to list processes
 676 
 677 ```java
 678 
 679 import java.foreign.*;
 680 import java.foreign.memory.*;
 681 import static org.unix.libproc_lib.*;
 682 
 683 public class LibprocMain {
 684     private static final int NAME_BUF_MAX = 256;
 685 
 686     public static void main(String[] args) {
 687         // Scope for native allocations
 688         try (Scope s = scope().fork()) {
 689             // get the number of processes
 690             int numPids = proc_listallpids(Pointer.ofNull(), 0);
 691             // allocate an array
 692             Array<Integer> pids = s.allocateArray(NativeTypes.INT32, numPids);
 693             // list all the pids into the native array
 694             proc_listallpids(pids.elementPointer(), numPids);
 695             // convert native array to java array
 696             int[] jpids = pids.toArray(num -> new int[num]);
 697             // buffer for process name
 698             Pointer<Byte> nameBuf = s.allocate(NativeTypes.INT8, NAME_BUF_MAX);
 699             for (int i = 0; i < jpids.length; i++) {
 700                 int pid = jpids[i];
 701                 // get the process name
 702                 proc_name(pid, nameBuf, NAME_BUF_MAX);
 703                 String procName = Pointer.toString(nameBuf);
 704                 // print pid and process name
 705                 System.out.printf("%d %s\n", pid, procName);
 706             }
 707         }
 708     }
 709 }
 710 
 711 ```
 712 
 713 ### Running the Java code that uses libproc
 714 
 715 ```sh
 716 
 717 javac -cp libproc.jar LibprocMain.java
 718 
 719 java -cp libproc.jar:. LibprocMain
 720 
 721 ```
 722 
 723 ## Using readline library from Java code (Mac OS)
 724 
 725 ### jextract a jar file for readline.h
 726 
 727 ```sh
 728 
 729 jextract -l readline -L /usr/local/opt/readline/lib/ --record-library-path \
 730     -t org.unix \
 731     /usr/include/readline/readline.h \
 732     --exclude-symbols readline_echoing_p -o readline.jar
 733 
 734 ```
 735 
 736 ### Java code that uses readline
 737 
 738 ```java
 739 
 740 import java.foreign.*;
 741 import java.foreign.memory.*;
 742 import static org.unix.readline_lib.*;
 743 
 744 public class Readline {
 745     public static void main(String[] args) {
 746         // Scope for native allocations
 747         try (Scope s = scope().fork()) {
 748             // allocate C memory initialized with Java string content
 749             var pstr = s.allocateCString("name? ");
 750 
 751             // call "readline" API
 752             var p = readline(pstr);
 753 
 754             // print char* as is
 755             System.out.println(p);
 756             // convert char* ptr from readline as Java String & print it
 757             System.out.println(Pointer.toString(p));
 758         }
 759     }
 760 }
 761 
 762 ```
 763 
 764 ### Running the java code that uses readline
 765 
 766 ```
 767 
 768 javac -cp readline.jar Readline.java
 769 
 770 java -cp readline.jar:. Readline
 771 
 772 ```
 773 
 774 ## Using libcurl from Java (Mac OS)
 775 
 776 ### jextract a jar for curl.h
 777 
 778 ```sh
 779 
 780 jextract -t org.unix -L /usr/lib -lcurl --record-library-path /usr/include/curl/curl.h -o curl.jar
 781 
 782 ```
 783 
 784 ### Java code that uses libcurl
 785 
 786 ```java
 787 
 788 import java.lang.invoke.*;
 789 import java.foreign.*;
 790 import java.foreign.memory.*;
 791 import org.unix.curl_lib;
 792 import static org.unix.curl_lib.*;
 793 import static org.unix.easy_lib.*;
 794 
 795 public class CurlMain {
 796    public static void main(String[] args) {
 797        try (Scope s = curl_lib.scope().fork()) {
 798            curl_global_init(CURL_GLOBAL_DEFAULT);
 799            Pointer<Void> curl = curl_easy_init();
 800            if(!curl.isNull()) {
 801                Pointer<Byte> url = s.allocateCString(args[0]);
 802                curl_easy_setopt(curl, CURLOPT_URL, url);
 803                int res = curl_easy_perform(curl);
 804                if (res != CURLE_OK) {
 805                    curl_easy_cleanup(curl);
 806                }
 807            }
 808            curl_global_cleanup();
 809        }
 810     }
 811 }
 812 
 813 ```
 814 
 815 ### Running the java code that uses libcurl
 816 
 817 ```sh
 818 
 819 javac -cp curl.jar CurlMain.java
 820 java -cp curl.jar:. CurlMain <url>
 821 
 822 ```
 823 
 824 ## Using unistd.h from Java code (Linux)
 825 
 826 ### jextract a jar file for unistd.h
 827 
 828 ```sh
 829 
 830 jextract /usr/include/unistd.h -t org.unix -o unistd.jar
 831 
 832 ```
 833 
 834 ### Java code that calls getpid
 835 
 836 ```java
 837 
 838 import java.foreign.*;
 839 import java.lang.invoke.*;
 840 import org.unix.unistd_h;
 841 
 842 
 843 public class Getpid {
 844     public static void main(String[] args) {
 845         // bind unistd interface
 846         var u = Libraries.bind(MethodHandles.lookup(), unistd_h.class);
 847         // call getpid from the unistd.h
 848         System.out.println(u.getpid());
 849         // check process id from Java API!
 850         System.out.println(ProcessHandle.current().pid());
 851     }
 852 }
 853 
 854 ```
 855 
 856 ### Running the Java code that uses getpid
 857 
 858 ```sh
 859 
 860 javac -cp unistd.jar Getpid.java
 861 
 862 java -cp unistd.jar:. Getpid
 863 
 864 ```
 865 
 866 
 867 ## Using OpenGL graphic library (Ubuntu 16.04)
 868 
 869 OpenGL is a popular portable graphic library: [https://www.opengl.org/](https://www.opengl.org/)
 870 
 871 ### Installing OpenGL (Ubuntu 16.04)
 872 
 873 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.
 874 
 875 OpenGL is always coupled with a bunch of other libraries, namely GLU and glut. You can install all those libraries using `apt`, as follows:
 876 
 877 ```sh
 878 
 879 sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
 880 
 881 ```
 882 
 883 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/`.
 884 
 885 ### jextracting OpenGL (Ubuntu 16.04)
 886 
 887 To extract the opengl libraries the following command suffices:
 888 
 889 ```sh
 890 
 891 jextract -L /usr/lib/x86_64-linux-gnu  -l glut -l GLU -l GL --record-library-path -t opengl -o opengl.jar /usr/include/GL/glut.h
 892 
 893 ```
 894 
 895 Since glut depends on the other libraries (GLU and GL), it is not necessary to give additional headers to jextract.
 896 
 897 ### Java sample code that uses the OpenGL library
 898 
 899 ```java
 900 import java.foreign.NativeTypes;
 901 import java.foreign.Scope;
 902 import java.foreign.memory.Array;
 903 import java.foreign.memory.Pointer;
 904 
 905 import static opengl.gl_lib.*;
 906 import static opengl.freeglut_std_lib.*;
 907 
 908 public class Teapot {
 909 
 910     float rot = 0;
 911 
 912     Teapot(Scope sc) {
 913         // Misc Parameters
 914         Array<Float> pos = sc.allocateArray(NativeTypes.FLOAT, new float[] {0.0f, 15.0f, -15.0f, 0});
 915         Array<Float> spec = sc.allocateArray(NativeTypes.FLOAT, new float[] {1, 1, 1, 0});
 916         Array<Float> shini = sc.allocateArray(NativeTypes.FLOAT, new float[] {113});
 917 
 918         // Reset Background
 919         glClearColor(0, 0, 0, 0);
 920 
 921         // Setup Lighting
 922         glShadeModel(GL_SMOOTH);
 923         glLightfv(GL_LIGHT0, GL_POSITION, pos.elementPointer());
 924         glLightfv(GL_LIGHT0, GL_AMBIENT, spec.elementPointer());
 925         glLightfv(GL_LIGHT0, GL_DIFFUSE, spec.elementPointer());
 926         glLightfv(GL_LIGHT0, GL_SPECULAR, spec.elementPointer());
 927         glMaterialfv(GL_FRONT, GL_SHININESS, shini.elementPointer());
 928         glEnable(GL_LIGHTING);
 929         glEnable(GL_LIGHT0);
 930         glEnable(GL_DEPTH_TEST);
 931     }
 932 
 933     void display() {
 934         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 935         glPushMatrix();
 936         glRotatef(-20, 1, 1, 0);
 937         glRotatef(rot, 0, 1, 0);
 938         glutSolidTeapot(0.5);
 939         glPopMatrix();
 940         glutSwapBuffers();
 941     }
 942 
 943     void onIdle() {
 944         rot += 0.1;
 945         glutPostRedisplay();
 946     }
 947 
 948     public static void main(String[] args) {
 949         try (Scope sc = opengl.gl_lib.scope().fork()) {
 950             Pointer<Integer> argc = sc.allocate(NativeTypes.INT32);
 951             argc.set(0);
 952             glutInit(argc, Pointer.ofNull());
 953             glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
 954             glutInitWindowSize(900, 900);
 955             glutCreateWindow(sc.allocateCString("Hello Panama!"));
 956             Teapot teapot = new Teapot(sc);
 957             glutDisplayFunc(sc.allocateCallback(teapot::display));
 958             glutIdleFunc(sc.allocateCallback(teapot::onIdle));
 959             glutMainLoop();
 960         }
 961     }
 962 }
 963 ```
 964 ### Running the Java code that uses OpenGL (Ubuntu 16.04)
 965 
 966 ```sh
 967 
 968 javac -cp opengl.jar Teapot.java
 969 
 970 java -cp opengl.jar:. Teapot
 971 
 972 ```
 973 
 974 ## Using OpenGL graphic library (Windows)
 975 
 976 ### Installing OpenGL
 977 
 978 Download the freeglut package for MSVC at [https://www.transmissionzero.co.uk/software/freeglut-devel/](https://www.transmissionzero.co.uk/software/freeglut-devel/)
 979 
 980 Extract the freeglut zip.
 981 
 982 ### jextracting OpenGL
 983 
 984 Navigate to the root directory of the extracted zip and run the following commands:
 985 
 986 ```powershell
 987 $inc = "C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0"
 988 jextract -L C:\Windows\System32\ -L .\freeglut\bin\x64\ -l opengl32 -l freeglut -t opengl -o opengl.jar --package-map "$inc\um\gl=opengl" --record-library-path .\freeglut\include\GL\glut.h
 989 ```
 990 
 991 The directory that is assigned to `$inc` is an example, and is system dependent. Make sure that the build number at the end of the path (in this case `10.0.17134.0`) is the latest one found in the parent folder (`C:\Program Files (x86)\Windows Kits\10\Include\`).
 992 
 993 There are a bunch of warnings generated, but as long as the jar file is generated in the working directory the extraction was successful.
 994 
 995 ### Java sample code that uses the OpenGL library
 996 
 997 This is the same as in the Ubuntu section
 998 
 999 ### Running the Java code that uses OpenGL
1000 
1001 ```powershell
1002 javac -cp .\opengl.jar Teapot.java
1003 java -cp "opengl.jar;." Teapot
1004 ```
1005 
1006 ## Using TensorFlow C API (Mac OS)
1007 
1008 Quoted from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c)
1009 
1010 "TensorFlow provides a C API that can be used to build bindings for other
1011 languages. The API is defined in c_api.h and designed for simplicity and
1012 uniformity rather than convenience."
1013 
1014 
1015 ### Installing libtensorflow
1016 
1017 You can follow the setup procedure as described in the above page.
1018 
1019 Alternatively, on Mac, you can install libtensorflow using HomeBrew
1020 
1021 ```sh
1022 
1023 brew install libtensorflow
1024 
1025 ```
1026 
1027 Tensorflow ship the libtensorflow with an .so extension, this doesn't work
1028 well for java on MacOS as java expect .dylib extension. To work around this,
1029 create a symbolic link.
1030 
1031 ```sh
1032 
1033 sudo ln -s /usr/local/lib/libtensorflow.so /usr/local/lib/libtensorflow.dylib
1034 
1035 ```
1036 
1037 ### jextracting libtensorflow c_api.h
1038 
1039 The following command can be used to extract c_api.h.
1040 
1041 ```sh
1042 
1043 jextract -C -x -C c++  \
1044         -L /usr/local/lib -l tensorflow --record-library-path \
1045         -o tf.jar -t org.tensorflow.panama \
1046         /usr/local/include/tensorflow/c/c_api.h
1047 
1048 ```
1049 
1050 The caveat to extract tensorflow C API is that it declare function prototype
1051 without argument in C++ style, for example, TF_Version(), which is considered
1052 incomplete C function prototype instead of C style as in TF_Version(void). An
1053 incomplete function prototype will become vararg funciton. To avoid that, we
1054 need to pass clang '-x c++' options to jextract with '-C -x -C c++'
1055 
1056 ### Java sample code that uses tensorflow library
1057 
1058 ```java
1059 
1060 import java.foreign.NativeTypes;
1061 import java.foreign.Scope;
1062 import java.foreign.memory.Array;
1063 import java.foreign.memory.LayoutType;
1064 import java.foreign.memory.Pointer;
1065 import org.tensorflow.panama.c_api_h.TF_DataType;
1066 import org.tensorflow.panama.c_api_h.TF_Graph;
1067 import org.tensorflow.panama.c_api_h.TF_Operation;
1068 import org.tensorflow.panama.c_api_h.TF_OperationDescription;
1069 import org.tensorflow.panama.c_api_h.TF_Output;
1070 import org.tensorflow.panama.c_api_h.TF_Session;
1071 import org.tensorflow.panama.c_api_h.TF_SessionOptions;
1072 import org.tensorflow.panama.c_api_h.TF_Status;
1073 import org.tensorflow.panama.c_api_h.TF_Tensor;
1074 
1075 import static org.tensorflow.panama.c_api_lib.*;
1076 import static org.tensorflow.panama.c_api_lib.TF_DataType.*;
1077 
1078 public class TensorFlowExample {
1079     static Pointer<TF_Operation> PlaceHolder(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1080                                       @TF_DataType int dtype, String name) {
1081         try (var s = scope().fork()) {
1082             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1083                     s.allocateCString("Placeholder"), s.allocateCString(name));
1084             TF_SetAttrType(desc, s.allocateCString("dtype"), TF_FLOAT);
1085             return TF_FinishOperation(desc, status);
1086         }
1087     }
1088 
1089     static Pointer<TF_Operation> ConstValue(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1090                                 Pointer<TF_Tensor> tensor, String name) {
1091         try (var s = scope().fork()) {
1092             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1093                     s.allocateCString("Const"), s.allocateCString(name));
1094             TF_SetAttrTensor(desc, s.allocateCString("value"), tensor, status);
1095             TF_SetAttrType(desc, s.allocateCString("dtype"), TF_TensorType(tensor));
1096             return TF_FinishOperation(desc, status);
1097         }
1098     }
1099 
1100     static Pointer<TF_Operation> Add(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1101                               Pointer<TF_Operation> one, Pointer<TF_Operation> two,
1102                               String name) {
1103         try (var s = scope().fork()) {
1104             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1105                     s.allocateCString("AddN"), s.allocateCString(name));
1106             Array<TF_Output> add_inputs = s.allocateArray(
1107                     LayoutType.ofStruct(TF_Output.class),2);
1108             add_inputs.get(0).oper$set(one);
1109             add_inputs.get(0).index$set(0);
1110             add_inputs.get(1).oper$set(two);
1111             add_inputs.get(1).index$set(0);
1112             TF_AddInputList(desc, add_inputs.elementPointer(), 2);
1113             return TF_FinishOperation(desc, status);
1114         }
1115     }
1116 
1117     public static void main(String... args) {
1118         System.out.println("TensorFlow C library version: " + Pointer.toString(TF_Version()));
1119 
1120         Pointer<TF_Graph> graph = TF_NewGraph();
1121         Pointer<TF_SessionOptions> options = TF_NewSessionOptions();
1122         Pointer<TF_Status> status = TF_NewStatus();
1123         Pointer<TF_Session> session = TF_NewSession(graph, options, status);
1124 
1125         float in_val_one = 4.0f;
1126         float const_two = 2.0f;
1127 
1128         Pointer<TF_Tensor> tensor_in = TF_AllocateTensor(TF_FLOAT, Pointer.ofNull(), 0, Float.BYTES);
1129         TF_TensorData(tensor_in).cast(NativeTypes.FLOAT).set(in_val_one);
1130         Pointer<TF_Tensor> tensor_const_two = TF_AllocateTensor(TF_FLOAT, Pointer.ofNull(), 0, Float.BYTES);
1131         TF_TensorData(tensor_const_two).cast(NativeTypes.FLOAT).set(const_two);
1132 
1133         // Operations
1134         Pointer<TF_Operation> feed = PlaceHolder(graph, status, TF_FLOAT, "feed");
1135         Pointer<TF_Operation> two = ConstValue(graph, status, tensor_const_two, "const");
1136         Pointer<TF_Operation> add = Add(graph, status, feed, two, "add");
1137 
1138 
1139         try (var s = scope().fork()) {
1140             var ltPtrTensor = LayoutType.ofStruct(TF_Tensor.class).pointer();
1141 
1142             // Session Inputs
1143             TF_Output input_operations = s.allocateStruct(TF_Output.class);
1144             input_operations.oper$set(feed);
1145             input_operations.index$set(0);
1146             Pointer<Pointer<TF_Tensor>> input_tensors = s.allocate(ltPtrTensor);
1147             input_tensors.set(tensor_in);
1148 
1149             // Session Outputs
1150             TF_Output output_operations = s.allocateStruct(TF_Output.class);
1151             output_operations.oper$set(add);
1152             output_operations.index$set(0);
1153             Pointer<Pointer<TF_Tensor>> output_tensors = s.allocate(ltPtrTensor);
1154             TF_SessionRun(session, Pointer.ofNull(),
1155                 // Inputs
1156                 input_operations.ptr(), input_tensors, 1,
1157                 // Outputs
1158                 output_operations.ptr(), output_tensors, 1,
1159                 // Target operations
1160                 Pointer.ofNull(), 0, Pointer.ofNull(),
1161                 status);
1162 
1163             System.out.println(String.format("Session Run Status: %d - %s",
1164                     TF_GetCode(status), Pointer.toString(TF_Message(status))));
1165             Pointer<TF_Tensor> tensor_out = output_tensors.get();
1166             System.out.println("Output Tensor Type: " + TF_TensorType(tensor_out));
1167             float outval = TF_TensorData(tensor_out).cast(NativeTypes.FLOAT).get();
1168             System.out.println("Output Tensor Value: " + outval);
1169 
1170             TF_CloseSession(session, status);
1171             TF_DeleteSession(session, status);
1172 
1173             TF_DeleteSessionOptions(options);
1174 
1175             TF_DeleteGraph(graph);
1176 
1177             TF_DeleteTensor(tensor_in);
1178             TF_DeleteTensor(tensor_out);
1179             TF_DeleteTensor(tensor_const_two);
1180 
1181             TF_DeleteStatus(status);
1182         }
1183     }
1184 }
1185 
1186 ```
1187 
1188 ### Compiling and running the above TensorFlow sample
1189 
1190 ```sh
1191 
1192 javac -cp tf.jar TensorFlowExample.java
1193 
1194 java -cp tf.jar:. TensorFlowExample
1195 
1196 ```
1197 
1198 ## Using TensorFlow C API (Windows)
1199 
1200 ### Installing libtensorflow
1201 
1202 You can download a binary distribution from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c)
1203 
1204 Extract the zip file.
1205 
1206 ### jextracting libtensorflow c_api.h
1207 
1208 The problem outlined in the Mac OS instruction w.r.t. incorrect function prototypes still exists (though it has been solved in the Tensorflow github repository, this change has not yet made it into the binary distributions). On Windows there is however no jextract command that works around this, so the only way to extract the \include\tensorflow\c\c_api.h header successfully is to first manually fix the incorrect function prototypes:
1209 
1210 ```C
1211 TF_Version() -> TF_Version(void)
1212 TF_NewGraph() -> TF_NewGraph(void)
1213 TF_NewSessionOptions() -> TF_NewSessionOptions(void)
1214 TF_NewStatus() -> TF_NewStatus(void)
1215 TF_NewBuffer() -> TF_NewBuffer(void)
1216 TF_NewImportGraphDefOptions() -> TF_NewImportGraphDefOptions(void)
1217 TF_GetAllOpList() -> TF_GetAllOpList(void)
1218 ```
1219 Once you've done this you can use the following jextract command from the libtensorflow root directory:
1220 
1221 ```powershell
1222 jextract -L .\lib -l tensorflow -o tf.jar -t "org.tensorflow.panama" --record-library-path .\include\tensorflow\c\c_api.h
1223 ```
1224 
1225 ### Java sample code that uses tensorflow library
1226 
1227 This is the same as for the Mac OS section.
1228 
1229 ### Compiling and running the above TensorFlow sample
1230 
1231 ```powershell
1232 javac -cp tf.jar TensorFlowExample.java
1233 java -cp "tf.jar;." TensorFlowExample
1234 ```