<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Otto Rask</title>
    <description>The latest articles on DEV Community by Otto Rask (@ojrask).</description>
    <link>https://dev.to/ojrask</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F144864%2Ff4751361-78f0-4475-823b-b5b1b24fc1d7.jpeg</url>
      <title>DEV Community: Otto Rask</title>
      <link>https://dev.to/ojrask</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ojrask"/>
    <language>en</language>
    <item>
      <title>Creating an FFI-compatible C-ABI library in Rust</title>
      <dc:creator>Otto Rask</dc:creator>
      <pubDate>Fri, 31 Jan 2020 09:15:19 +0000</pubDate>
      <link>https://dev.to/verkkokauppacom/creating-an-ffi-compatible-c-abi-library-in-rust-5dji</link>
      <guid>https://dev.to/verkkokauppacom/creating-an-ffi-compatible-c-abi-library-in-rust-5dji</guid>
      <description>&lt;p&gt;This is part 2 in our PHP FFI + Rust blog series. Previously we took a look at how the FFI feature can be enabled and used in PHP 7.4, and now we will jump over to Rust and see how we can create C-ABI libraries ourselves, which can then be loaded using PHP FFI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;C would be the obvious first choice when writing C-ABI libraries, yes. But alas, I am more versed in Rust than in C. I know how Rust works in general and what features are available, but am not an expert by any means, while I only know how to compile a C program and that's about it.&lt;/p&gt;

&lt;p&gt;When using Rust there are some extra steps needed when compiling C-ABI compatible libraries, namely making sure our compiled code and logic is aligned and packed according to the C standard and creating a header file which C-ABI consumers can use to locate our code which they want to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;We will be working with stable Rust and a single external crate in this post. I assume you have Rust and Cargo installed and are ready to compile Rust programs from the command line. I am working on Linux Ubuntu, but the steps should be similar for other environments as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example code
&lt;/h2&gt;

&lt;p&gt;All code introduced in the series is available at GitHub in the &lt;a href="https://github.com/rask/php-ffi-examples" rel="noopener noreferrer"&gt;examples repository&lt;/a&gt; I have created. Check the &lt;code&gt;201-rusty-hello-world&lt;/code&gt; directory, which contains a runnable example for the code we're about to write here in this post. You can edit and tinker with the code on your own machine and see what happens.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rask" rel="noopener noreferrer"&gt;
        rask
      &lt;/a&gt; / &lt;a href="https://github.com/rask/php-ffi-examples" rel="noopener noreferrer"&gt;
        php-ffi-examples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Runnable examples to learn how PHP FFI works
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Rust Hello World
&lt;/h2&gt;

&lt;p&gt;First we want to make a regular non-C-ABIfied Rust library just to have a starting point for this post. We will take this starting library and convert it to a C-ABI dynamic library in later steps.&lt;/p&gt;

&lt;p&gt;Let's initialize a new blank library:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cargo init --lib my-library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With the skeleton in place, we can check it works by running &lt;code&gt;cargo test&lt;/code&gt; which should return a passed test for the dummy test we have been scaffolded in &lt;code&gt;src/lib.rs&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can go in and write a Hello World library for the greater good! Open the project in an editor of your choice, and let's begin by altering the unit test inside &lt;code&gt;lib.rs&lt;/code&gt;. We want to have a function that returns the string &lt;code&gt;Hello world!&lt;/code&gt; to whomever calls it.&lt;/p&gt;

&lt;p&gt;Our test could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_library_function_returns_correct_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We call a function and expect it to return &lt;code&gt;"Hello world!"&lt;/code&gt;. Simple stuff so far. Let's run the test:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cargo test
error[E0425]: cannot find function `get_hello_world` in this scope
 --&amp;gt; src/lib.rs:5:22
  |
5 |         let result = get_hello_world();
  |                      ^^^^^^^^^^^^^^^ not found in this scope

error: aborting due to previous error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Oh no! Our function is nowhere to be found! Let's fix that. In the &lt;code&gt;lib.rs&lt;/code&gt; file, create a new function to fix our error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="cd"&gt;/// Return a hello world string to the caller.&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_library_function_returns_correct_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created a new function, and also added &lt;code&gt;use super::*;&lt;/code&gt; to the &lt;code&gt;tests&lt;/code&gt; module definition to load it into the test scope. Now if we attempt to run tests, we are greeted with a &lt;em&gt;compilation&lt;/em&gt; error instead of a test failure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0308]: mismatched types
  --&amp;gt; src/lib.rs:11:27
   |
11 |         assert!(result == String::from("Hello world!"));
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::string::String`
   |
   = note: expected type `()`
              found type `std::string::String`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the compiler knew the function was available, but type checking failed as we are not returning a &lt;code&gt;String&lt;/code&gt; from the &lt;code&gt;get_hello_world()&lt;/code&gt; function. Let's fix that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's test again:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;running 1 test
test tests::test_library_function_returns_correct_string ... FAILED

failures:

---- tests::test_library_function_returns_correct_string stdout ----
thread 'tests::test_library_function_returns_correct_string' panicked at 'assertion failed: result == String::from("Hello world!")', src/lib.rs:13:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    tests::test_library_function_returns_correct_string

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We did not get compilation errors, which is great, and now our actual testcase failed. We can see that a string was returned (because it compiled) but the strings do not match. To see what the comparison contains, we can convert to &lt;code&gt;assert_eq!()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_library_function_returns_correct_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now when we run &lt;code&gt;cargo test&lt;/code&gt; we get a better understanding what we are exactly comparing:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;running 1 test
test tests::test_library_function_returns_correct_string ... FAILED

failures:

---- tests::test_library_function_returns_correct_string stdout ----
thread 'tests::test_library_function_returns_correct_string' panicked at 'assertion failed: `(left == right)`
  left: `""`,
 right: `"Hello world!"`', src/lib.rs:13:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    tests::test_library_function_returns_correct_string

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Pay attention to the lines starting with &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;. We see the right side is the expected value from our test, and the left side does not match. We now need to fix our code to make them match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our tests should pass gloriously:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;running 1 test
test tests::test_library_function_returns_correct_string ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests example-01-hello-world-library

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Woot!&lt;/p&gt;

&lt;p&gt;We now have a library we could package up and ship to &lt;a href="https://crates.io" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; for others to use! But let's not do that, as we have other plans. Time to make it C-ABI compatible!&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing C-compatible Rust
&lt;/h2&gt;

&lt;p&gt;Writing C-compatible Rust might sound scary, complicated, and strange, but it really is not too difficult. Rust and C share quite a bit in the ABI-compatibility department, meaning &lt;em&gt;in general&lt;/em&gt; Rust can be compiled as a C library assuming you're not doing anything strange.&lt;/p&gt;

&lt;p&gt;The biggest pain point is converting between C and Rust data types and memory guarantees.&lt;/p&gt;

&lt;p&gt;Assuming our library function in Rust returns a &lt;code&gt;String&lt;/code&gt;, which is an entirely Rust concept, we cannot use that directly in C. What we can do, is juggle with a raw pointer (gasp!) and convert the data held by our &lt;code&gt;String&lt;/code&gt; into a C-friendlier format.&lt;/p&gt;

&lt;p&gt;Let's introduce two new functions which become our public API over C-ABI. Add the following functions and tests for them in the &lt;code&gt;lib.rs&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ffi&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;c_hello_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rust_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert the String into a CString&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rust_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not convert to CString"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Instead of returning the CString, we return a pointer for it.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c_string&lt;/span&gt;&lt;span class="nf"&gt;.into_raw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;c_hello_world_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="nf"&gt;.is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// No data there, already freed probably.&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Here we reclaim ownership of the data the pointer points to, to free the memory properly.&lt;/span&gt;
        &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_library_function_returns_correct_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_library_cabi_function_works&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;c_char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;c_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cstring&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cstring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;cstring&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The good old &lt;code&gt;get_hello_world()&lt;/code&gt; function has been left as is, but we've introduced a new function that calls it: &lt;code&gt;c_hello_world()&lt;/code&gt;. We also have a secondary function &lt;code&gt;c_hello_world_free(ptr: *mut c_char)&lt;/code&gt;, which is used to free the memory that the first function has reserved. We will take a look at it later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;c_hello_world()&lt;/code&gt; looks like a regular Rust function, but with some sprinkling on top:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;#[no_mangle]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;extern "C"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-&amp;gt; *mut c_char&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;no_mangle&lt;/code&gt; attribute instructs the Rust compiler to not alter the function name when it is inserted to a binary file. This makes it easier for FFI users to call it, as the name is kept as "human-readable".&lt;/p&gt;

&lt;p&gt;Writing &lt;code&gt;extern "C"&lt;/code&gt; defines that this function should be callable outside Rust codebases, and the &lt;code&gt;"C"&lt;/code&gt; portion instructs the Rust compiler to optimize the function for usage in C-ABI consumers.&lt;/p&gt;

&lt;p&gt;The return type on the other hand is a raw pointer. A mutable one at that. Scared yet? I know I am.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;cargo test&lt;/code&gt; should see the test passes for this new function as well. In the test function we call the C-compatible function, and assert that it produces a pointer to a string that is stored in C format (&lt;code&gt;CString&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Raw pointers as explained by a Rust newbie
&lt;/h3&gt;

&lt;p&gt;Rust has two of these raw pointer thingies: &lt;code&gt;*const T&lt;/code&gt; and &lt;code&gt;*mut T&lt;/code&gt;, where T is the type of data the pointer points to in memory. The &lt;code&gt;*const&lt;/code&gt; and &lt;code&gt;*mut&lt;/code&gt; parts seem like they are some dereferencing operator thingies, but they are not. They are literal type declarations for raw pointers. I was confused as well.&lt;/p&gt;

&lt;p&gt;It is relatively rare to need to use these types of pointers when you're working on a pure Rust code base. They offer some powers that regular Rust does not provide, and are also required when interfacing with other languages, such as C.&lt;/p&gt;

&lt;p&gt;What raw pointers essentially allow us to do is move stuff between the Rust world and C world using them. Well not move the stuff itself, but more like give an adress from Rust to C and vice versa: "The thing you want is here at this address, but I am not helping you with how to use it or process it". Yay pointers!&lt;/p&gt;

&lt;p&gt;The data raw pointers point at can be anything. It could be &lt;code&gt;*const String&lt;/code&gt;, or maybe &lt;code&gt;*mut MyStruct&lt;/code&gt;. The type declaration just lets Rust know what it might be working with.&lt;/p&gt;

&lt;p&gt;Working with raw pointers is &lt;code&gt;unsafe&lt;/code&gt; in Rust, meaning you need to know what you're doing with them. For simple things you can get away with one or two &lt;code&gt;unsafe&lt;/code&gt; blocks, but for complex stuff, you must pay attention. Otherwise you're corrupting or leaking information in memory.&lt;/p&gt;

&lt;p&gt;Passing the pointers themselves around is not &lt;code&gt;unsafe&lt;/code&gt;, but the second you want to read, modify, or delete the data they point to, you are in &lt;code&gt;unsafe&lt;/code&gt; territory.&lt;/p&gt;

&lt;p&gt;You also need to make sure the data behind raw pointers is freed properly. In Rust terms, when we create a raw pointer, we lose ownership and lifetime guarantees to a degree.&lt;/p&gt;

&lt;p&gt;In our code we use &lt;code&gt;CString::into_raw()&lt;/code&gt; and &lt;code&gt;CString::from_raw()&lt;/code&gt; to momentarily release Rust ownership to C land, and then take it back. The &lt;code&gt;from_raw()&lt;/code&gt; also triggers lifetime checks, and frees the data/memory using Rust rules. If you do not do this, you will most probably leak memory in you programs.&lt;/p&gt;

&lt;p&gt;You should also check if you're working with a null pointer before doing anything with the data the pointer may or may not point to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/ptr/index.html" rel="noopener noreferrer"&gt;Read more about pointers at the Rust documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the &lt;code&gt;*_free&lt;/code&gt; function?
&lt;/h3&gt;

&lt;p&gt;We added two functions for our C-ABI compatible API. One creates a &lt;code&gt;CString&lt;/code&gt;, and the other is supposed to free memory which was created for the &lt;code&gt;CString&lt;/code&gt;. How does this work and why is it done this way?&lt;/p&gt;

&lt;p&gt;In C, you are in charge of memory. This means you are responsible for allocating memory, and freeing memory. Rust itself has guarantees in place that allow you to skip the low-level stuff most of the time, but in C you need to be more careful.&lt;/p&gt;

&lt;p&gt;With our C-ABI we are allocating memory inside Rust, and then passing that memory pointer to someone outside Rust. This creates a situation where we "disable" the Rust borrow checker and lifetime rules for that allocation. Someone outside Rust can erase the memory, alter it, and so on.&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;free&lt;/code&gt; function, we provide a tool for the external code to return control of memory to Rust, after which Rust is again in charge with borrow checks and other guarantees.&lt;/p&gt;

&lt;p&gt;In terms of FFI, we first call &lt;code&gt;c_hello_world()&lt;/code&gt; which allocates memory inside Rust and provides us with a pointer to the allocation (&lt;code&gt;T::into_raw()&lt;/code&gt;). After we're done using the memory, we call &lt;code&gt;c_hello_world_free()&lt;/code&gt; with the same pointer which we received earlier, and then inside Rust we "consume" (&lt;code&gt;T::from_raw()&lt;/code&gt;) that pointer to return control back to Rust.&lt;/p&gt;

&lt;p&gt;A similar pattern is already in use inside PHP. &lt;code&gt;fopen()&lt;/code&gt; and &lt;code&gt;fclose()&lt;/code&gt; follows the same semantics for example. You open a resource, do work with it, and then you close it to prevent mistakes from happening, even if that would just mean a memory leak or similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compiling into a C library
&lt;/h2&gt;

&lt;p&gt;When we compile our example library right now, we only get a Rust library out of it (&lt;code&gt;.rlib&lt;/code&gt;), which is quite useless if we want to use the library in a C-ABI FFI setup.&lt;/p&gt;

&lt;p&gt;To alter what is compiled and where, we need to alter our &lt;code&gt;Cargo.toml&lt;/code&gt; configuration.&lt;/p&gt;

&lt;p&gt;If you have not touched it since we initialized the project, it should look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package]
name = "my-library"
version = "0.1.0"
authors = ["John Doe &amp;lt;johndoe@example.com&amp;gt;"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Quite bare, and a good starting point.&lt;/p&gt;

&lt;p&gt;To change our compilation from a Rust library to a dynamic C library, we need to introduce a &lt;code&gt;[lib]&lt;/code&gt; definition:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

[dependencies]

[lib]
name = "my_library"
crate-type = ["cdylib"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After that is in there, running &lt;code&gt;cargo build&lt;/code&gt; should result in a &lt;code&gt;libmy_library.so&lt;/code&gt; library appearing inside &lt;code&gt;target/debug&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hey, now we could take that file and use it in PHP! Does the following look familiar?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ok this is missing for now'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'libmy_library.so'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat stuff. The only thing we now need is a header. Let's create a new file into the &lt;code&gt;target/debug&lt;/code&gt; directory (for now, later we will move those things elsewhere) called &lt;code&gt;my_library.h&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define FFI_LIB "libmy_library.so"

char *const c_hello_world();
void c_hello_world_free(char *const str);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;libmy_library.so&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;my_library.h&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use those in PHP as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/path/to/library.h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'/path/to/libmy_library.so'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$cstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;c_hello_world&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$phpstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cstr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;c_hello_world_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cstr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$phpstr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running that should output &lt;code&gt;Hello world!&lt;/code&gt; in your terminal. How cool! Notice we first called the string (read: pointer) returning function, and after we read the contents to a PHP string, we call the memory freeing function to make sure we are not creating leaks.&lt;/p&gt;

&lt;p&gt;Next up: how to automate writing these C header files, instead of manually tinkering with them every time our C-ABI API changes in Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating C headers generation with &lt;code&gt;cbindgen&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In the Rust ecosystem, there are a multitude of libraries and tools with &lt;code&gt;bindgen&lt;/code&gt; in their names. &lt;code&gt;cbindgen&lt;/code&gt;, &lt;code&gt;wasm-bindgen&lt;/code&gt;, etc. The naming comes from "bindings generator", and they are used to assist in creating cross language and cross binary bindings. With &lt;code&gt;cbindgen&lt;/code&gt; we can create bindings (headers) from Rust in a C-ABI compatible way.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;cbindgen&lt;/code&gt; for really small projects might be overkill, but I would say it is not a big dependency to depend on maintenance-wise.&lt;/p&gt;

&lt;p&gt;To get &lt;code&gt;cbindgen&lt;/code&gt; we need to modify our &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

[dependencies]

[build-dependencies]
cbindgen = "0.9.*"

...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We added a new section, called &lt;code&gt;build-dependencies&lt;/code&gt;. This means Cargo will install those to be used in a crate build process, not the crate contents itself. &lt;code&gt;cbindgen&lt;/code&gt; is used during the build process, so we install it this way.&lt;/p&gt;

&lt;p&gt;Now you can run &lt;code&gt;cargo update&lt;/code&gt; and it will fetch and install the dependency.&lt;/p&gt;

&lt;p&gt;Once installed, we need to create a build step. Cargo supports a thing called build scripts, which are bare Rust files that are invoked when building a crate. Create a &lt;code&gt;build.rs&lt;/code&gt; file next to &lt;code&gt;Cargo.toml&lt;/code&gt;, and insert the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;cbindgen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;cbindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;crate_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CARGO_MANIFEST_DIR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nn"&gt;cbindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.with_crate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crate_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.with_language&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to generate bindings"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.write_to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"target/debug/my_library.h"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is short, and the only thing we do is instantiate a &lt;code&gt;cbindgen&lt;/code&gt; builder instance, alter the configuration a bit, then generate and write the headers to a wanted location on the filesystem.&lt;/p&gt;

&lt;p&gt;To make Cargo use this build file, we need to add it to the &lt;code&gt;Cargo.toml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package]
name = "my-library"
version = "0.1.0"
authors = ["John Doe &amp;lt;johndoe@example.com&amp;gt;"]
edition = "2018"
build = "build.rs"

...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice the &lt;code&gt;build&lt;/code&gt; key containing the &lt;code&gt;build.rs&lt;/code&gt; file path.&lt;/p&gt;

&lt;p&gt;When we now run &lt;code&gt;cargo build&lt;/code&gt;, hopefully we see some header generation magic happen.&lt;/p&gt;

&lt;p&gt;(Note: I had to run &lt;code&gt;build&lt;/code&gt; twice, as somehow the &lt;code&gt;cbindgen&lt;/code&gt; crate had to be compiled in two runs, try it if nothing appears that looks like a header file.)&lt;/p&gt;

&lt;p&gt;Once compilation is done, check the &lt;code&gt;target/debug&lt;/code&gt; directory. Can you see the &lt;code&gt;my_library.h&lt;/code&gt; file? Check the contents. It should show a header similar to the one we manually wrote earlier, but now it has some new stuff. This means the &lt;code&gt;cbindgen&lt;/code&gt; build worked, and now we have automated the generation of header files for our C-ABI library.&lt;/p&gt;

&lt;p&gt;What &lt;code&gt;cbindgen&lt;/code&gt; does, is it parses our source code for definitions that are marked as &lt;code&gt;extern "C"&lt;/code&gt; or similar, and generates the bindings automatically based on those.&lt;/p&gt;

&lt;p&gt;We would like to have &lt;code&gt;cbindgen&lt;/code&gt; automatically insert the &lt;code&gt;FFI_LIB&lt;/code&gt; definition into the header as well, in order to be able to use the &lt;code&gt;\FFI::load()&lt;/code&gt; method instead of the &lt;code&gt;\FFI::cdef()&lt;/code&gt; method in our PHP code. Also there are some unwanted includes in the header which are not needed with PHP FFI as far as I know.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cbindgen&lt;/code&gt; currently has no configurability for creating constants like &lt;code&gt;FFI_LIB&lt;/code&gt;, but we can hack those in using the &lt;code&gt;cbindgen::Builder::with_header()&lt;/code&gt; method. Add the following changes to &lt;code&gt;build.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;cbindgen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.with_crate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crate_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.with_language&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.with_no_includes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// First we strip the default include lines which are not needed&lt;/span&gt;
    &lt;span class="nf"&gt;.with_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#define FFI_LIB &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;libmy_library.so&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// then we insert our custom definitions, the .so path is relative to the header file we're writing&lt;/span&gt;
    &lt;span class="nf"&gt;.generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to generate bindings"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.write_to_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"target/debug/my_library.h"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A bit hacky, yes, but works. Now if you run &lt;code&gt;cargo build&lt;/code&gt;, the header should contain a new line which defines the &lt;code&gt;FFI_LIB&lt;/code&gt; constant, and the default includes should be gone. Now we have a header file which is compatible with &lt;code&gt;\FFI::load()&lt;/code&gt; in PHP land.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Okay, so now we know how to write basic C-ABI and FFI-ready libraries in Rust, and also took a super quick peek at how to use those in PHP via FFI. Additionally we looked at how to use &lt;code&gt;cbindgen&lt;/code&gt; to do some tedious work for us automatically.&lt;/p&gt;

&lt;p&gt;Homework: try and see if you can work out how to add a user-supplied parameter to the &lt;code&gt;get_hello_world&lt;/code&gt; and &lt;code&gt;c_hello_world&lt;/code&gt; functions, so they can return &lt;code&gt;Hello World, &amp;lt;param&amp;gt;!&lt;/code&gt; or similar.&lt;/p&gt;

&lt;p&gt;In the upcoming posts in this series we will be writing some more complicated code, meaning we need to learn a bit about the various types that are available in PHP FFI from the C-ABI, and how to write Rust code that operates on those types as well.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>c</category>
      <category>ffi</category>
      <category>php</category>
    </item>
    <item>
      <title>Introduction to PHP FFI</title>
      <dc:creator>Otto Rask</dc:creator>
      <pubDate>Mon, 18 Nov 2019 14:59:11 +0000</pubDate>
      <link>https://dev.to/verkkokauppacom/introduction-to-php-ffi-po3</link>
      <guid>https://dev.to/verkkokauppacom/introduction-to-php-ffi-po3</guid>
      <description>&lt;p&gt;In this series of posts, we will be getting acquainted with a new PHP feature: FFI!&lt;/p&gt;

&lt;p&gt;In addition to getting to know PHP FFI, we will be learning how to create and use FFI libraries written in Rust.&lt;/p&gt;

&lt;p&gt;FFI is a new addition to PHP starting from version 7.4. In a nutshell, it allows you to run external binary code via a wrapper written in PHP. The binary code can be anything which supports the C-ABI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: I am not a C/Rust/ABI/FFI expert, I am writing this series to learn things as a PHP developer as well. If you see errors or other things that should be changed, please do let me know.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  FFI? ABI?
&lt;/h2&gt;

&lt;p&gt;FFI (&lt;a href="https://en.wikipedia.org/wiki/Foreign_function_interface" rel="noopener noreferrer"&gt;&lt;em&gt;Foreign Function Interface&lt;/em&gt;&lt;/a&gt;) is a way for two separate codebases to integrate via an ABI (&lt;a href="https://en.wikipedia.org/wiki/Application_binary_interface" rel="noopener noreferrer"&gt;&lt;em&gt;Application Binary Interface&lt;/em&gt;&lt;/a&gt;). One of the most common ABIs for FFI usage is the C-ABI, which defines the binary calling conventions and data structures for compiled C programs. The C-ABI convention is supported by various other non-C languages a well, such as Rust.&lt;/p&gt;

&lt;p&gt;In essence you can load and call code from a C library inside PHP, or any other language that supports FFI via C-ABI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would I want to use FFI?
&lt;/h2&gt;

&lt;p&gt;FFI is great if you need to run resource intensive code and your "own" programming language is not up to the task (e.g. extensive parsing, number crunching, complex rendering, etc.). Instead of using two entirely different programs to do a single thing in steps, you can "glue" two codebases together inside a single program to do the single thing more efficiently. Or maybe you have a good C-ABI library readily available, and just want to save time by not rewriting it in PHP for instance.&lt;/p&gt;

&lt;p&gt;FFI can provide performance boosts, but sometimes it might actually make your programs slower. We will be looking at some simple benchmarks on what works well and what does not at some point. Tricky business, but hopefully we can find the good spots where FFI will be of help. If not, we will see good and bad use-cases in the future when more PHP folks start using FFI.&lt;/p&gt;

&lt;p&gt;Python has become one of the most popular languages for machine learning and number crunching partly because of FFI. It is relatively simple to load and use powerful C-ABI libraries in Python (via FFI), which in itself is a relatively easy language to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to expect from this blog series
&lt;/h2&gt;

&lt;p&gt;This series will walk us through the following in some way or another:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Introduction FFI in PHP (this post),&lt;/li&gt;
&lt;li&gt;  Creating FFI-libraries for PHP in the Rust programming language,&lt;/li&gt;
&lt;li&gt;  How to use C types in PHP,&lt;/li&gt;
&lt;li&gt;  Benchmarking a few FFI use-cases, to see when FFI is the more performant choice and vice versa,&lt;/li&gt;
&lt;li&gt;  Creating sane and testable FFI abstractions in PHP,&lt;/li&gt;
&lt;li&gt;  How to properly integrate FFI with the PHP preloading feature,&lt;/li&gt;
&lt;li&gt;  Creating distributable PHP Composer packages that make use of FFI,&lt;/li&gt;
&lt;li&gt;  Ensuring safety when writing and using FFI libraries in PHP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I mainly use Linux Ubuntu when programming, so you may have to alter the steps I describe throughout this series to make things work right in other environments. Occasionally I might show a cross-platform way to do things, but do not rely on those working as I have no other systems to test things out on at the moment.&lt;/p&gt;

&lt;p&gt;I am writing this series mainly for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; It gives me a good excuse to learn more about PHP, FFI, Rust, and C,&lt;/li&gt;
&lt;li&gt; It gives me a good excuse to teach somebody something useful, as I like to do when blogging.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So hopefully I will learn new stuff and you will learn at least a thing or two as well in the process.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Example source code
&lt;/h2&gt;

&lt;p&gt;To support the blog series, I have created a code repository that contains example code. The examples are runnable, meaning you can see what happens when you run them and change things.&lt;/p&gt;

&lt;p&gt;The example code is available at &lt;a href="https://github.com/rask/php-ffi-examples" rel="noopener noreferrer"&gt;github.com/rask/php-ffi-examples&lt;/a&gt;. You can download/clone the repository to your machine to run and modify as you wish. If you see errors there, you can create issues or send pull requests.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rask" rel="noopener noreferrer"&gt;
        rask
      &lt;/a&gt; / &lt;a href="https://github.com/rask/php-ffi-examples" rel="noopener noreferrer"&gt;
        php-ffi-examples
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Runnable examples to learn how PHP FFI works
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;To run the PHP examples, you need a FFI-compatible PHP interpreter build, which we'll take a look at next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing and configuring FFI for PHP
&lt;/h2&gt;

&lt;p&gt;PHP 7.4 ships with FFI built in. It is a core &lt;em&gt;extension&lt;/em&gt;, meaning it can be disabled. PHP can also be compiled without the FFI extension.&lt;/p&gt;

&lt;p&gt;At the time of writing, PHP 7.4 is still under unstable version development. This means we do not have any official stable builds available for PHP FFI coding.&lt;/p&gt;

&lt;p&gt;If you do not have a FFI-enabled PHP build available, you may have to compile a compatible binary of PHP yourself. NOTE: Some popular package repositories provide unstable PHP 7.4 builds that have FFI enabled.&lt;/p&gt;

&lt;p&gt;There are tons of guides online for compiling PHP from sources in various ways, but if you're somewhat familiar with the process or compiling C programs in general, you can follow the steps outlined below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;build-essential autoconf automake libtool bison re2c
&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/php/php-src
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;php-src
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout php-7.4.0beta4
&lt;span class="nv"&gt;$ &lt;/span&gt;./buildconf
&lt;span class="nv"&gt;$ &lt;/span&gt;./configure &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/&amp;lt;user&amp;gt;/php/7.4.0beta4 &lt;span class="nt"&gt;--with-ffi&lt;/span&gt; &lt;span class="nt"&gt;--with-zlib&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;make
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We pass in &lt;code&gt;--with-zlib&lt;/code&gt; to be able to use some compressed data such as compressed PHARs while working. You may need a dependency for it. With &lt;code&gt;--prefix&lt;/code&gt; we set where the installation process puts the compiled binaries and other required data.&lt;/p&gt;

&lt;p&gt;After these steps (if successful) you will have a PHP CLI binary sitting in &lt;code&gt;/home/&amp;lt;user&amp;gt;/php/7.4.0beta4/bin/php&lt;/code&gt;. You can check that FFI is available by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;/home/&amp;lt;user&amp;gt;/php/7.4.0beta4/bin/php &lt;span class="nt"&gt;-m&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;FFI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the FFI module is not loaded, verify your build configuration, build steps, and the generated &lt;code&gt;php.ini&lt;/code&gt; file (found inside &lt;code&gt;/home/&amp;lt;user&amp;gt;/php/7.4.0beta4/lib&lt;/code&gt; or a similar location).&lt;/p&gt;

&lt;p&gt;I recommend adding the built PHP binary to your &lt;code&gt;$PATH&lt;/code&gt;, as we will be using it on the command line quite a bit over the course of this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring PHP FFI
&lt;/h2&gt;

&lt;p&gt;By default FFI is enabled only in the following cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; You're running PHP using the CLI SAPI (i.e. you're running PHP scripts in your terminal or via cron or similar use-cases)&lt;/li&gt;
&lt;li&gt; You're using the new PHP 7.4 preloading feature when running a web application&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to disable FFI, you need to alter your &lt;code&gt;php.ini&lt;/code&gt;. Look for a line similar to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;ffi.enable&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;preload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And set the value from &lt;code&gt;preload&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;. If the line is prefixed with a &lt;code&gt;;&lt;/code&gt; comment marker, remove the marker as well.&lt;/p&gt;

&lt;p&gt;If you want to have FFI enabled &lt;em&gt;at all times&lt;/em&gt; instead, you can set the value to &lt;code&gt;true&lt;/code&gt;. This means FFI is available outside preload and CLI. You might really want to reconsider using this setting in production environments, as it will most probably make your application slower and less safe. For web application development environments it might be a good choice, as you do not need to rely on the preload mechanism when working on your code, and implement the preloading mechanism later on.&lt;/p&gt;

&lt;p&gt;Now that we have PHP with FFI available, we can start coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  FFI Hello World
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Example code provided in &lt;a href="https://github.com/rask/php-ffi-examples/tree/master/101-hello-world" rel="noopener noreferrer"&gt;&lt;code&gt;101-hello-world&lt;/code&gt;&lt;/a&gt; directory of the examples repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What would a tutorial or series be without a &lt;em&gt;Hello World&lt;/em&gt; example? Behold:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'void printf(char *const str, ...);'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'libc.so.6'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello %s!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run it, it should print &lt;code&gt;Hello world!&lt;/code&gt; into your terminal window, as expected from a hello world program.&lt;/p&gt;

&lt;p&gt;Now let's go through it piece by piece.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Here we begin creating a new FFI definition.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// `cdef` is used to first input C headers, then provide the location of a C-ABI&lt;/span&gt;
&lt;span class="c1"&gt;// library that provides the implementation for the header.&lt;/span&gt;
&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

    &lt;span class="c1"&gt;// Here we provide the C header. It can be a string, which is loaded&lt;/span&gt;
    &lt;span class="c1"&gt;// from an actual file as well using `file_get_contents()` or similar.&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="c1"&gt;// In this example we define the `printf` function that accepts a regular&lt;/span&gt;
    &lt;span class="c1"&gt;// string. Note the `...`, which is for C variadics.&lt;/span&gt;
    &lt;span class="s1"&gt;'void printf(char *const str, ...);'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// Next we point to the C-ABI library file that hosts the&lt;/span&gt;
    &lt;span class="c1"&gt;// implementation itself.&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="c1"&gt;// In this example we load the global system `libc.so` library, meaning the C&lt;/span&gt;
    &lt;span class="c1"&gt;// standard library. This may or may not exist depending on your setup,&lt;/span&gt;
    &lt;span class="c1"&gt;// meaning you need to validate which library file to load.&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="c1"&gt;// The "6" at the end is part of the filename, and carries no special meaning&lt;/span&gt;
    &lt;span class="c1"&gt;// in terms of loading a library.&lt;/span&gt;
    &lt;span class="s1"&gt;'libc.so.6'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Lastly, we make use of the generated FFI definition. We have the&lt;/span&gt;
&lt;span class="c1"&gt;// functions defined in the C header available to be used through&lt;/span&gt;
&lt;span class="c1"&gt;// the FFI object.&lt;/span&gt;
&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello %s!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good. We now know how to load a C-ABI library and call its functions from PHP. And it is not really that verbose either! If you want a PHP analogy, it looks a little like we're using a factory method to instantiate a class filled with magic methods that have been defined elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternate method for loading
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Example code provided in &lt;a href="https://github.com/rask/php-ffi-examples/tree/master/102-hello-world-with-load" rel="noopener noreferrer"&gt;&lt;code&gt;102-hello-world-with-load&lt;/code&gt;&lt;/a&gt; directory of the examples repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can use the &lt;code&gt;cdef&lt;/code&gt; method for loading a library, but you may also use the &lt;code&gt;load&lt;/code&gt; method, which loads and parses a single C header file and infers the library to load from it.&lt;/p&gt;

&lt;p&gt;Given you have a C header file called &lt;code&gt;header.h&lt;/code&gt; written as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define FFI_LIB "libc.so.6"

void printf(char *const str, ...);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;FFI_LIB&lt;/code&gt; definition is used to set the path to a dynamic library that should be loaded for this header file.&lt;/p&gt;

&lt;p&gt;Otherwise it can be a somewhat regular C header file.&lt;/p&gt;

&lt;p&gt;You can replace the &lt;code&gt;cdef&lt;/code&gt; in the hello world example above with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/header.h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello %s!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the loading a little simpler, and you get some separation of concerns when it comes to defining what libraries you intend to use, and what functions and other goodies you want to use from those libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoped method for loading
&lt;/h2&gt;

&lt;p&gt;There is a third method for loading a C library, using a feature called FFI scopes.&lt;/p&gt;

&lt;p&gt;Scopes are available only when you are using the PHP 7.4 preloading functionality. The following example is really simple and unrunnable, and you will need to setup your preloading configuration and scripts properly if you intend to use scopes.&lt;/p&gt;

&lt;p&gt;Given you have a &lt;code&gt;header.h&lt;/code&gt; file as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define FFI_SCOPE "helloworld"
#define FFI_LIB "libc.so.6"

void printf(char *const str, ...);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then use something like the following in your preloading script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/header.h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;my_printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This string argument is the same as the&lt;/span&gt;
        &lt;span class="c1"&gt;// `FFI_SCOPE` definition in the `header.h` file&lt;/span&gt;
        &lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'helloworld'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$subs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then in your "nonpreloading" normal code you could call FFI as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;my_printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello %s!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is of course a very bare example, and you also need the preloading configuration and boilerplate in place to make use of scopes properly. Scoped loading is preferred when preloading, as it provides some performance improvements over the &lt;code&gt;cdef&lt;/code&gt; and &lt;code&gt;load&lt;/code&gt; methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  FFI errors
&lt;/h2&gt;

&lt;p&gt;The FFI feature throws errors in a few situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Invalid library header or binary definition for &lt;code&gt;cdef&lt;/code&gt; and friends,&lt;/li&gt;
&lt;li&gt;  Runtime errors when accessing FFI state or resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if your C header is malformed, you will be greeted with an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'hello this is invalid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'libc.so.6'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will throw an &lt;code&gt;\FFI\ParserException&lt;/code&gt; which lets you know that your header is not valid.&lt;/p&gt;

&lt;p&gt;When accessing resources that do not exist (e.g. are not available in the loaded C-ABI library), you might receive something like follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'void idonotexist();'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'libc.so.6'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// PHP Fatal error:  Uncaught FFI\Exception: Failed resolving C function 'idonotexist'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you attempt to call a C-ABI function that does not exist, you receive the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'void printf(char *const str, ...);'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'libc.so.6'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Above is fine and works, but now we attempt to call something that is not available:&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Uncaught FFI\Exception: Attempt to call undefined C function 'some_function'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try loading a C-ABI library that does not exist, another exception is thrown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cdef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'void printf(char *const str, ...);'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'idonotexist.so'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Uncaught FFI\Exception: Failed loading 'idonotexist.so'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling errors
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Example code provided in &lt;a href="https://github.com/rask/php-ffi-examples/tree/master/103-hello-world-with-trycatch" rel="noopener noreferrer"&gt;&lt;code&gt;103-hello-world-with-trycatch&lt;/code&gt;&lt;/a&gt; directory of the examples repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All FFI errors are either instances of &lt;code&gt;\FFI\Exception&lt;/code&gt;, or descendants of it. So the simplest approach to making your FFI loading a little less fragile is to use a generic try-catch as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/header.h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\FFI\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// log error, do fail tasks, prevent running, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello %s!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple example. We have not taken care of the following situation for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$ffi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;\FFI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/header.h'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\FFI\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// log error, do fail tasks, prevent running, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$ffi&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;function_which_is_not_defined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// oops&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handling raw FFI exceptions is not the best solution, and you will most probably want to abstract your FFI interactions behind a class or similar, which provides saner error handling itself.&lt;/p&gt;

&lt;p&gt;Another option could be to run some up-front tests against the FFI instance during loading or in automated tests to make sure the library works. This might not work well enough in the end though.&lt;/p&gt;

&lt;p&gt;In any case these are outside the scope of this introductory post, and we will look at FFI abstractions in a later installment of this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;In this part we took a look at the requirements for FFI installation and configuration, and also learned a few ways to load and use a C library inside PHP using FFI.&lt;/p&gt;

&lt;p&gt;In the next part, we're going to learn how to write a C-ABI library using Rust, and hopefully learn a bit about how the C-ABI works and how Rust libraries should be constructed to be a little more FFI-friendly.&lt;/p&gt;

</description>
      <category>php</category>
      <category>ffi</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
