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_lib.*;
  52 import static org.python.pythonrun_lib.*;
  53 
  54 public class PythonMain {
  55     public static void main(String[] args) {
  56         Py_Initialize();
  57         try (Scope s = org.python.Python_lib.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_h.*;
 172 import static org.sqlite.sqlite3_lib.*;
 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_lib.*;
 357 import static blas.cblas_lib.CBLAS_ORDER.*;
 358 import static blas.cblas_lib.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        @blas.cblas_h.CBLAS_ORDER int Layout;
 367        @blas.cblas_h.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_lib.*;
 461 import static lapack.cblas_lib.*;
 462 
 463 public class TestLapack {
 464     public static void main(String[] args) {
 465 
 466         /* Locals */
 467         try (Scope sc = lapack.clapack_lib.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_lib.*;
 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_lib.*;
 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_lib.*;
 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_lib;
 729 import static org.unix.curl_lib.*;
 730 import static org.unix.easy_lib.*;
 731 
 732 public class CurlMain {
 733    public static void main(String[] args) {
 734        try (Scope s = curl_lib.scope().fork()) { 
 735            curl_global_init(CURL_GLOBAL_DEFAULT);
 736            Pointer<Void> curl = curl_easy_init();
 737            if(!curl.isNull()) {
 738                Pointer<Byte> url = s.allocateCString(args[0]);
 739                curl_easy_setopt(curl, CURLOPT_URL, url);
 740                int res = curl_easy_perform(curl);
 741                if (res != CURLE_OK) {
 742                    curl_easy_cleanup(curl);
 743                }
 744            }
 745            curl_global_cleanup();
 746        }
 747     }
 748 }
 749 
 750 ```
 751 
 752 ### Running the java code that uses libcurl
 753 
 754 ```sh
 755 
 756 javac -cp curl.jar CurlMain.java
 757 java -cp curl.jar:. CurlMain <url>
 758 
 759 ```
 760 
 761 ## Using unistd.h from Java code (Linux)
 762 
 763 ### jextract a jar file for unistd.h
 764 
 765 ```sh
 766 
 767 jextract /usr/include/unistd.h -t org.unix -o unistd.jar
 768 
 769 ```
 770 
 771 ### Java code that calls getpid
 772 
 773 ```java
 774 
 775 import java.foreign.*;
 776 import java.lang.invoke.*;
 777 import org.unix.unistd_h;
 778 
 779 
 780 public class Getpid {
 781     public static void main(String[] args) {
 782         // bind unistd interface
 783         var u = Libraries.bind(MethodHandles.lookup(), unistd_h.class);
 784         // call getpid from the unistd.h
 785         System.out.println(u.getpid());
 786         // check process id from Java API!
 787         System.out.println(ProcessHandle.current().pid());
 788     }
 789 }
 790 
 791 ```
 792 
 793 ### Running the Java code that uses getpid
 794 
 795 ```sh
 796 
 797 javac -cp unistd.jar Getpid.java
 798 
 799 java -cp unistd.jar:. Getpid
 800 
 801 ```
 802 
 803 
 804 ## Using OpenGL graphic library (Ubuntu 16.04)
 805 
 806 OpenGL is a popular portable graphic library: [https://www.opengl.org/](https://www.opengl.org/)
 807 
 808 ### Installing OpenGL (Ubuntu 16.04)
 809 
 810 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.
 811 
 812 OpenGL is always coupled with a bunch of other libraries, namely GLU and glut. You can install all those libraries using `apt`, as follows:
 813 
 814 ```sh
 815 
 816 sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
 817 
 818 ```
 819 
 820 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/`.
 821 
 822 ### jextracting OpenGL (Ubuntu 16.04)
 823 
 824 To extract the opengl libraries the following command suffices:
 825 
 826 ```sh
 827 
 828 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
 829 
 830 ```
 831 
 832 Since glut depends on the other libraries (GLU and GL), it is not necessary to give additional headers to jextract.
 833 
 834 ### Java sample code that uses the OpenGL library
 835 
 836 ```java
 837 import java.foreign.NativeTypes;
 838 import java.foreign.Scope;
 839 import java.foreign.memory.Array;
 840 import java.foreign.memory.Pointer;
 841 
 842 import static opengl.gl_lib.*;
 843 import static opengl.freeglut_std_lib.*;
 844 
 845 public class Teapot {
 846 
 847     float rot = 0;
 848 
 849     Teapot(Scope sc) {
 850         // Misc Parameters
 851         Array<Float> pos = sc.allocateArray(NativeTypes.FLOAT, new float[] {0.0f, 15.0f, -15.0f, 0});
 852         Array<Float> spec = sc.allocateArray(NativeTypes.FLOAT, new float[] {1, 1, 1, 0});
 853         Array<Float> shini = sc.allocateArray(NativeTypes.FLOAT, new float[] {113});
 854 
 855         // Reset Background
 856         glClearColor(0, 0, 0, 0);
 857 
 858         // Setup Lighting
 859         glShadeModel(GL_SMOOTH);
 860         glLightfv(GL_LIGHT0, GL_POSITION, pos.elementPointer());
 861         glLightfv(GL_LIGHT0, GL_AMBIENT, spec.elementPointer());
 862         glLightfv(GL_LIGHT0, GL_DIFFUSE, spec.elementPointer());
 863         glLightfv(GL_LIGHT0, GL_SPECULAR, spec.elementPointer());
 864         glMaterialfv(GL_FRONT, GL_SHININESS, shini.elementPointer());
 865         glEnable(GL_LIGHTING);
 866         glEnable(GL_LIGHT0);
 867         glEnable(GL_DEPTH_TEST);
 868     }
 869 
 870     void display() {
 871         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 872         glPushMatrix();
 873         glRotatef(-20, 1, 1, 0);
 874         glRotatef(rot, 0, 1, 0);
 875         glutSolidTeapot(0.5);
 876         glPopMatrix();
 877         glutSwapBuffers();
 878     }
 879 
 880     void onIdle() {
 881         rot += 0.1;
 882         glutPostRedisplay();
 883     }
 884 
 885     public static void main(String[] args) {
 886         try (Scope sc = opengl.gl_lib.scope().fork()) {
 887             Pointer<Integer> argc = sc.allocate(NativeTypes.INT32);
 888             argc.set(0);
 889             glutInit(argc, Pointer.ofNull());
 890             glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
 891             glutInitWindowSize(900, 900);
 892             glutCreateWindow(sc.allocateCString("Hello Panama!"));
 893             Teapot teapot = new Teapot(sc);
 894             glutDisplayFunc(sc.allocateCallback(teapot::display));
 895             glutIdleFunc(sc.allocateCallback(teapot::onIdle));
 896             glutMainLoop();
 897         }
 898     }
 899 }
 900 ```
 901 ### Running the Java code that uses OpenGL (Ubuntu 16.04)
 902 
 903 ```sh
 904 
 905 javac -cp opengl.jar Teapot.java
 906 
 907 java -cp opengl.jar:. Teapot
 908 
 909 ```
 910 
 911 ## Using OpenGL graphic library (Windows)
 912 
 913 ### Installing OpenGL
 914 
 915 Download the freeglut package for MSVC at [https://www.transmissionzero.co.uk/software/freeglut-devel/](https://www.transmissionzero.co.uk/software/freeglut-devel/)
 916 
 917 Extract the freeglut zip.
 918 
 919 ### jextracting OpenGL
 920 
 921 Navigate to the root directory of the extracted zip and run the following commands:
 922 
 923 ```powershell
 924 $inc = "C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0"
 925 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
 926 ```
 927 
 928 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\`).
 929 
 930 There are a bunch of warnings generated, but as long as the jar file is generated in the working directory the extraction was successful.
 931 
 932 ### Java sample code that uses the OpenGL library
 933 
 934 This is the same as in the Ubuntu section
 935 
 936 ### Running the Java code that uses OpenGL
 937 
 938 ```powershell
 939 javac -cp .\opengl.jar Teapot.java
 940 java -cp "opengl.jar;." Teapot
 941 ```
 942 
 943 ## Using TensorFlow C API (Mac OS)
 944 
 945 Quoted from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c)
 946 
 947 "TensorFlow provides a C API that can be used to build bindings for other
 948 languages. The API is defined in c_api.h and designed for simplicity and
 949 uniformity rather than convenience."
 950 
 951 
 952 ### Installing libtensorflow
 953 
 954 You can follow the setup procedure as described in the above page.
 955 
 956 Alternatively, on Mac, you can install libtensorflow using HomeBrew
 957 
 958 ```sh
 959 
 960 brew install libtensorflow
 961 
 962 ```
 963 
 964 Tensorflow ship the libtensorflow with an .so extension, this doesn't work
 965 well for java on MacOS as java expect .dylib extension. To work around this,
 966 create a symbolic link.
 967 
 968 ```sh
 969 
 970 sudo ln -s /usr/local/lib/libtensorflow.so /usr/local/lib/libtensorflow.dylib
 971 
 972 ```
 973 
 974 ### jextracting libtensorflow c_api.h
 975 
 976 The following command can be used to extract c_api.h.
 977 
 978 ```sh
 979 
 980 jextract -C -x -C c++  \
 981         -L /usr/local/lib -l tensorflow --record-library-path \
 982         -o tf.jar -t org.tensorflow.panama \
 983         /usr/local/include/tensorflow/c/c_api.h
 984 
 985 ```
 986 
 987 The caveat to extract tensorflow C API is that it declare function prototype
 988 without argument in C++ style, for example, TF_Version(), which is considered
 989 incomplete C function prototype instead of C style as in TF_Version(void). An
 990 incomplete function prototype will become vararg funciton. To avoid that, we
 991 need to pass clang '-x c++' options to jextract with '-C -x -C c++'
 992 
 993 ### Java sample code that uses tensorflow library
 994 
 995 ```java
 996 
 997 import java.foreign.NativeTypes;
 998 import java.foreign.Scope;
 999 import java.foreign.memory.Array;
1000 import java.foreign.memory.LayoutType;
1001 import java.foreign.memory.Pointer;
1002 import org.tensorflow.panama.c_api_h.TF_DataType;
1003 import org.tensorflow.panama.c_api_h.TF_Graph;
1004 import org.tensorflow.panama.c_api_h.TF_Operation;
1005 import org.tensorflow.panama.c_api_h.TF_OperationDescription;
1006 import org.tensorflow.panama.c_api_h.TF_Output;
1007 import org.tensorflow.panama.c_api_h.TF_Session;
1008 import org.tensorflow.panama.c_api_h.TF_SessionOptions;
1009 import org.tensorflow.panama.c_api_h.TF_Status;
1010 import org.tensorflow.panama.c_api_h.TF_Tensor;
1011 
1012 import static org.tensorflow.panama.c_api_lib.*;
1013 import static org.tensorflow.panama.c_api_lib.TF_DataType.*;
1014 
1015 public class TensorFlowExample {
1016     static Pointer<TF_Operation> PlaceHolder(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1017                                       @TF_DataType int dtype, String name) {
1018         try (var s = scope().fork()) {
1019             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1020                     s.allocateCString("Placeholder"), s.allocateCString(name));
1021             TF_SetAttrType(desc, s.allocateCString("dtype"), TF_FLOAT);
1022             return TF_FinishOperation(desc, status);
1023         }
1024     }
1025 
1026     static Pointer<TF_Operation> ConstValue(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1027                                 Pointer<TF_Tensor> tensor, String name) {
1028         try (var s = scope().fork()) {
1029             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1030                     s.allocateCString("Const"), s.allocateCString(name));
1031             TF_SetAttrTensor(desc, s.allocateCString("value"), tensor, status);
1032             TF_SetAttrType(desc, s.allocateCString("dtype"), TF_TensorType(tensor));
1033             return TF_FinishOperation(desc, status);
1034         }
1035     }
1036 
1037     static Pointer<TF_Operation> Add(Pointer<TF_Graph> graph, Pointer<TF_Status> status,
1038                               Pointer<TF_Operation> one, Pointer<TF_Operation> two,
1039                               String name) {
1040         try (var s = scope().fork()) {
1041             Pointer<TF_OperationDescription> desc = TF_NewOperation(graph,
1042                     s.allocateCString("AddN"), s.allocateCString(name));
1043             Array<TF_Output> add_inputs = s.allocateArray(
1044                     LayoutType.ofStruct(TF_Output.class),2);
1045             add_inputs.get(0).oper$set(one);
1046             add_inputs.get(0).index$set(0);
1047             add_inputs.get(1).oper$set(two);
1048             add_inputs.get(1).index$set(0);
1049             TF_AddInputList(desc, add_inputs.elementPointer(), 2);
1050             return TF_FinishOperation(desc, status);
1051         }
1052     }
1053 
1054     public static void main(String... args) {
1055         System.out.println("TensorFlow C library version: " + Pointer.toString(TF_Version()));
1056 
1057         Pointer<TF_Graph> graph = TF_NewGraph();
1058         Pointer<TF_SessionOptions> options = TF_NewSessionOptions();
1059         Pointer<TF_Status> status = TF_NewStatus();
1060         Pointer<TF_Session> session = TF_NewSession(graph, options, status);
1061 
1062         float in_val_one = 4.0f;
1063         float const_two = 2.0f;
1064 
1065         Pointer<TF_Tensor> tensor_in = TF_AllocateTensor(TF_FLOAT, Pointer.ofNull(), 0, Float.BYTES);
1066         TF_TensorData(tensor_in).cast(NativeTypes.FLOAT).set(in_val_one);
1067         Pointer<TF_Tensor> tensor_const_two = TF_AllocateTensor(TF_FLOAT, Pointer.ofNull(), 0, Float.BYTES);
1068         TF_TensorData(tensor_const_two).cast(NativeTypes.FLOAT).set(const_two);
1069 
1070         // Operations
1071         Pointer<TF_Operation> feed = PlaceHolder(graph, status, TF_FLOAT, "feed");
1072         Pointer<TF_Operation> two = ConstValue(graph, status, tensor_const_two, "const");
1073         Pointer<TF_Operation> add = Add(graph, status, feed, two, "add");
1074 
1075 
1076         try (var s = scope().fork()) {
1077             var ltPtrTensor = LayoutType.ofStruct(TF_Tensor.class).pointer();
1078 
1079             // Session Inputs
1080             TF_Output input_operations = s.allocateStruct(TF_Output.class);
1081             input_operations.oper$set(feed);
1082             input_operations.index$set(0);
1083             Pointer<Pointer<TF_Tensor>> input_tensors = s.allocate(ltPtrTensor);
1084             input_tensors.set(tensor_in);
1085 
1086             // Session Outputs
1087             TF_Output output_operations = s.allocateStruct(TF_Output.class);
1088             output_operations.oper$set(add);
1089             output_operations.index$set(0);
1090             Pointer<Pointer<TF_Tensor>> output_tensors = s.allocate(ltPtrTensor);
1091             TF_SessionRun(session, Pointer.ofNull(),
1092                 // Inputs
1093                 input_operations.ptr(), input_tensors, 1,
1094                 // Outputs
1095                 output_operations.ptr(), output_tensors, 1,
1096                 // Target operations
1097                 Pointer.ofNull(), 0, Pointer.ofNull(),
1098                 status);
1099 
1100             System.out.println(String.format("Session Run Status: %d - %s",
1101                     TF_GetCode(status), Pointer.toString(TF_Message(status))));
1102             Pointer<TF_Tensor> tensor_out = output_tensors.get();
1103             System.out.println("Output Tensor Type: " + TF_TensorType(tensor_out));
1104             float outval = TF_TensorData(tensor_out).cast(NativeTypes.FLOAT).get();
1105             System.out.println("Output Tensor Value: " + outval);
1106 
1107             TF_CloseSession(session, status);
1108             TF_DeleteSession(session, status);
1109 
1110             TF_DeleteSessionOptions(options);
1111 
1112             TF_DeleteGraph(graph);
1113 
1114             TF_DeleteTensor(tensor_in);
1115             TF_DeleteTensor(tensor_out);
1116             TF_DeleteTensor(tensor_const_two);
1117 
1118             TF_DeleteStatus(status);
1119         }
1120     }
1121 }
1122 
1123 ```
1124 
1125 ### Compiling and running the above TensorFlow sample
1126 
1127 ```sh
1128 
1129 javac -cp tf.jar TensorFlowExample.java
1130 
1131 java -cp tf.jar:. TensorFlowExample
1132 
1133 ```
1134 
1135 ## Using TensorFlow C API (Windows)
1136 
1137 ### Installing libtensorflow
1138 
1139 You can download a binary distribution from [https://www.tensorflow.org/install/lang_c](https://www.tensorflow.org/install/lang_c)
1140 
1141 Extract the zip file.
1142 
1143 ### jextracting libtensorflow c_api.h
1144 
1145 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:
1146 
1147 ```C
1148 TF_Version() -> TF_Version(void)  
1149 TF_NewGraph() -> TF_NewGraph(void)  
1150 TF_NewSessionOptions() -> TF_NewSessionOptions(void)  
1151 TF_NewStatus() -> TF_NewStatus(void)
1152 TF_NewBuffer() -> TF_NewBuffer(void)
1153 TF_NewImportGraphDefOptions() -> TF_NewImportGraphDefOptions(void)
1154 TF_GetAllOpList() -> TF_GetAllOpList(void)
1155 ```
1156 Once you've done this you can use the following jextract command from the libtensorflow root directory:
1157 
1158 ```powershell
1159 jextract -L .\lib -l tensorflow -o tf.jar -t "org.tensorflow.panama" --record-library-path .\include\tensorflow\c\c_api.h
1160 ```
1161 
1162 ### Java sample code that uses tensorflow library
1163 
1164 This is the same as for the Mac OS section.
1165 
1166 ### Compiling and running the above TensorFlow sample
1167 
1168 ```powershell
1169 javac -cp tf.jar TensorFlowExample.java
1170 java -cp "tf.jar;." TensorFlowExample
1171 ```