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