summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2024/09/12/Functional-Reactive-Programming-in-F/index.html16
-rw-r--r--2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/index.html367
-rw-r--r--2024/09/15/肩周炎和肩袖损伤的区别/index.html282
-rw-r--r--archives/2024/09/index.html36
-rw-r--r--archives/2024/index.html60
-rw-r--r--archives/2024/page/2/index.html60
-rw-r--r--archives/2024/page/3/index.html58
-rw-r--r--archives/2024/page/4/index.html36
-rw-r--r--archives/index.html62
-rw-r--r--archives/page/10/index.html56
-rw-r--r--archives/page/11/index.html224
-rw-r--r--archives/page/2/index.html62
-rw-r--r--archives/page/3/index.html60
-rw-r--r--archives/page/4/index.html64
-rw-r--r--archives/page/5/index.html62
-rw-r--r--archives/page/6/index.html62
-rw-r--r--archives/page/7/index.html62
-rw-r--r--archives/page/8/index.html62
-rw-r--r--archives/page/9/index.html66
-rw-r--r--page/11/index.html230
-rw-r--r--search.xml133
-rw-r--r--tag/index.html18
-rw-r--r--tags/Archive/index.html246
-rw-r--r--tags/Life/index.html36
-rw-r--r--tags/Life/page/2/index.html18
-rw-r--r--tags/Medicine/index.html36
-rw-r--r--tags/Medicine/page/2/index.html36
-rw-r--r--tags/Medicine/page/3/index.html18
-rw-r--r--tags/OCaml/index.html36
-rw-r--r--tags/OCaml/page/2/index.html18
-rw-r--r--tags/Technique/index.html36
-rw-r--r--tags/Technique/page/2/index.html36
-rw-r--r--tags/Technique/page/3/index.html18
33 files changed, 2167 insertions, 505 deletions
diff --git a/2024/09/12/Functional-Reactive-Programming-in-F/index.html b/2024/09/12/Functional-Reactive-Programming-in-F/index.html
index dd82f7a2..301be807 100644
--- a/2024/09/12/Functional-Reactive-Programming-in-F/index.html
+++ b/2024/09/12/Functional-Reactive-Programming-in-F/index.html
@@ -147,6 +147,12 @@
</span>
<span class="post-tag">
+ <a href="/tags/Archive/">
+ Archive
+ </a>
+ </span>
+
+ <span class="post-tag">
<a href="/tags/F/">
F#
</a>
@@ -172,7 +178,10 @@
</div>
</div>
<div class="post-content">
- <p>Events are everywhere. Almost every program has to handle events, whether it be button clicks in the user interface, listening to sockets in a server, or even a system shutdown notification.</p>
+ <blockquote>
+<p><a target="_blank" rel="noopener" href="https://fsharpforfunandprofit.com/posts/concurrency-reactive/">https://fsharpforfunandprofit.com/posts/concurrency-reactive/</a></p>
+</blockquote>
+<p>Events are everywhere. Almost every program has to handle events, whether it be button clicks in the user interface, listening to sockets in a server, or even a system shutdown notification.</p>
<p>And events are the basis of one of the most common OO design patterns: the “Observer” pattern.</p>
<p>But as we know, event handling, like concurrency in general, can be tricky to implement. Simple event logic is straightforward, but what about logic like “do something if two events happen in a row but do something different if only one event happens” or “do something if two events happen at roughly the same time”. And how easy is it to combine these requirements in other, more complex ways?</p>
<p>Even if you can successfully implement these requirements, the code tends to be spaghetti like and hard to understand, even with the best intentions.</p>
@@ -297,6 +306,11 @@
<nav class="post-nav">
<div class="prev-item">
+ <div class="icon arrow-left"></div>
+ <div class="post-link">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">Prev</a>
+ </div>
+
</div>
<div class="next-item">
diff --git a/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/index.html b/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/index.html
new file mode 100644
index 00000000..781eeb0e
--- /dev/null
+++ b/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/index.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>Advanced C binding using ocaml-ctypes and dune | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <article id="post">
+
+
+ <div class="post-head">
+ <div class="post-info">
+ <div class="tag-list">
+
+
+ <span class="post-tag">
+ <a href="/tags/Technique/">
+ Technique
+ </a>
+ </span>
+
+ <span class="post-tag">
+ <a href="/tags/OCaml/">
+ OCaml
+ </a>
+ </span>
+
+ <span class="post-tag">
+ <a href="/tags/Archive/">
+ Archive
+ </a>
+ </span>
+
+
+ </div>
+ <div class="post-title">
+
+
+ Advanced C binding using ocaml-ctypes and dune
+
+
+ </div>
+ <span class="post-date">
+ Sep 15, 2024
+ </span>
+ </div>
+ <div class="post-img">
+
+ <div class="h-line-primary"></div>
+
+ </div>
+</div>
+ <div class="post-content">
+ <p>I was working on a OCaml binding for <a target="_blank" rel="noopener" href="https://github.com/Haivision/srt">libsrt</a> last summer, to add support for SRT real-time input and output to <a target="_blank" rel="noopener" href="https://github.com/savonet/liquidsoap">liquidsoap</a>, and came across the need to access the <code>[sys/socket.h](https://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html)</code> C API.</p>
+<p>I had already decided to use the very elegant <code>[ocaml-ctypes](https://github.com/ocamllabs/ocaml-ctypes)</code> module for the SRT binding so I went with it and created a <code>[ocaml-sys-socket](https://github.com/toots/ocaml-sys-socket)</code> module using it as well. It was a very interesting experience that I would like to describe here!</p>
+<h1 id="ocaml-ctypes"><a href="#ocaml-ctypes" class="headerlink" title="ocaml-ctypes"></a>ocaml-ctypes</h1><p>The idea behind OCaml ctypes is to create a binding against a C library without having to write C code, or as least as possible. The most straight-forward way of using it is via <code>[libffi](https://github.com/libffi/libffi)</code> , providing access to dynamically-loaded libraries.</p>
+<p>The second way of using it is by letting the module generate the basic C stubs required to build and link against a shared library. This is the mode that we’re going to use here. In this mode, the programmer has to describe the C headers of the library they intent to bind to using dedicated OCaml modules, operators and types. From that description, ocaml-ctypes is able to generate the required glue for the binding.</p>
+<p>One advantage of using ocaml-ctypes is that the created bindings make as few assumptions as possible about the <a target="_blank" rel="noopener" href="https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html">OCaml C interfacing API</a>. This is pretty nice, in particular since the <a target="_blank" rel="noopener" href="https://github.com/ocaml/ocaml">OCaml compiler</a> is moving pretty quickly these days (which is awesome!) and also if, perhaps one day, <a target="_blank" rel="noopener" href="https://github.com/ocaml-multicore/ocaml-multicore">support for multi-core</a> is added to the compiler, which will undoubtedly change the C interface API quite a bit.</p>
+<h1 id="dune"><a href="#dune" class="headerlink" title="dune"></a>dune</h1><p><code>[dune](https://github.com/ocaml/dune)</code> (formally <code>jbuilder</code> ) is a build system for OCaml projects that has recently raised to much popularity, particularly due to its tight integration with the rest of the OCaml ecosystem, such as <code>[ocamlfind](http://projects.camlcity.org/projects/findlib.html)</code> and <code>[opam](https://opam.ocaml.org/)</code> .</p>
+<p>My personal motto in programming in general is that <em>“Simple things should be simple, but complex things should be possible”</em>. <code>dune</code> certainly does not fit into that category but, rather, makes some complex things extremely easy to setup. It’s the kind of tool that will make your life incredibly easier when what you intent to do fits well within their workflow but might not be easy to bend to some very specific niche use. We will see one such case below.</p>
+<p>At any rate, it’s been an amazing experience getting to learn how to use <code>dune</code> and the resulting code and build system is remarkably short and elegant, yet very powerful.</p>
+<h1 id="socket-h"><a href="#socket-h" class="headerlink" title="socket.h"></a>socket.h</h1><p><code>socket.h</code> is the Unix header that describes the C API to various socket operations, IP version 4 and 6 as well as unix file sockets. There is also a windows API mimicking it, which makes most code using it easily portable to windows.</p>
+<p>Most network-based C libraries refer to <code>socket.h</code> to describe the type of socket that can be used with their API so it’s an important entry point for a lot of network operations and one that would be nice to support as generically as possible in OCaml.</p>
+<p>The catch, though, is that, most likely for historical reasons¹, the <a target="_blank" rel="noopener" href="https://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html">POSIX specifications</a> only <em>partially</em> defines some of the required data structures and types, which makes it possible to write C code using them but does not give enough information to write C bindings without having to use the compiler to parse the actual system-specific headers of the running host.</p>
+<p>For instance, here’s how the <code>sockaddr</code> structure is specified:</p>
+<p>The <em>&lt;sys&#x2F;socket.h&gt;</em> header defines the <strong>sockaddr</strong> structure that includes at least the following members:sa_family_t sa_family address family<br>char sa_data[] socket address (variable-length data)</p>
+<p>Likewise, here’s what is specified about the size of the <code>socklen_t</code> data type:</p>
+<p><em>&lt;sys&#x2F;socket.h&gt;</em> makes available a type, <strong>socklen_t</strong>, which is an unsigned opaque integral type of length of at least 32 bits.</p>
+<p>Thus, in order to know the exact offset of <code>sa_family</code> inside the <code>sockaddr</code> structure or the actual size of a <code>socklen_t</code> integer, one has to include the OS-specific header, parse its definitions for that specific OS and, only then, is it possible to compute that offset or data size. Let’s see how it’s done in our binding now!</p>
+<h1 id="Putting-it-together"><a href="#Putting-it-together" class="headerlink" title="Putting it together"></a>Putting it together</h1><p>The C binding requires 4 separate passes:</p>
+<ul>
+<li>The <code>[constants](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/constants)</code> pass, which computes and exports some specific constant and data sizes, computed from the C headers</li>
+<li>The <code>[types](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/types)</code> pass, which, given the system-specific constants and sizes exported in the previous phase, defines the actual C data structure bindings.</li>
+<li>The <code>[stubs](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/stubs)</code> pass, where we define the actual bindings to the C functions that we wish to export in our API.</li>
+<li>Finally, the <a target="_blank" rel="noopener" href="https://github.com/toots/ocaml-sys-socket/blob/master/src/sys-socket/sys_socket.mli">last pass</a> does a cleanup of the <code>stubs</code> pass to export a relevant and OCaml- (and <code>ocaml-ctypes</code>) specific public API that is to be used by users of the module.</li>
+</ul>
+<p><code>dune</code> makes each of these steps fairly easy to integrate into the next one, defining compilation elements and binaries to build before moving to the next pass.</p>
+<h2 id="Constants-pass"><a href="#Constants-pass" class="headerlink" title="Constants pass"></a>Constants pass</h2><p>During that pass, we compute and export all required C values defined in the headers. We also add our own constants, which give us the sizes that the POSIX specifications leave up to the OS. Here’s the OCaml code for it:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">let</span> af_inet = <span class="type">S</span>.constant <span class="string">&quot;AF_INET&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_inet6 = <span class="type">S</span>.constant <span class="string">&quot;AF_INET6&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_unix = <span class="type">S</span>.constant <span class="string">&quot;AF_UNIX&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_unspec = <span class="type">S</span>.constant <span class="string">&quot;AF_UNSPEC&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sa_data_len = <span class="type">S</span>.constant <span class="string">&quot;SA_DATA_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sa_family_len = <span class="type">S</span>.constant <span class="string">&quot;SA_FAMILY_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_dgram = <span class="type">S</span>.constant <span class="string">&quot;SOCK_DGRAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_stream = <span class="type">S</span>.constant <span class="string">&quot;SOCK_STREAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_seqpacket = <span class="type">S</span>.constant <span class="string">&quot;SOCK_STREAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> socklen_t_len = <span class="type">S</span>.constant <span class="string">&quot;SOCKLEN_T_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_maxserv = <span class="type">S</span>.constant <span class="string">&quot;NI_MAXSERV&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_maxhost = <span class="type">S</span>.constant <span class="string">&quot;NI_MAXHOST&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_numerichost = <span class="type">S</span>.constant <span class="string">&quot;NI_NUMERICHOST&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_numericserv = <span class="type">S</span>.constant <span class="string">&quot;NI_NUMERICSERV&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>Pretty straightforward! Some of these constants are defined by the POSIX headers and some are custom defined for our needs, for instance <code>SOCKLEN_T_LEN</code> . Here’s how they are extracted, using the <code>dune</code> build configuration for <code>[gen_constants_c](https://github.com/toots/ocaml-sys-socket/blob/master/src/sys-socket/generator/gen_constants_c.ml)</code>:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;sys/un.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#define SA_DATA_LEN (sizeof(((struct sockaddr*)0)-&gt;sa_data))</span></span><br><span class="line"><span class="string">#define SA_FAMILY_LEN (sizeof(((struct sockaddr*)0)-&gt;sa_family))</span></span><br><span class="line"><span class="string">#define SOCKLEN_T_LEN (sizeof(socklen_t))</span></span><br><span class="line"><span class="string">#ifndef NI_MAXHOST</span></span><br><span class="line"><span class="string"> #define NI_MAXHOST 1025</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#ifndef NI_MAXSERV</span></span><br><span class="line"><span class="string"> #define NI_MAXSERV 32</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.<span class="type">Types</span>.write_c format (<span class="keyword">module</span> <span class="type">Sys_socket_constants</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>This OCaml code makes use of <code>ocaml-ctypes</code> to build a binary that exports the OCaml interface defined by <code>Sys_socket_constants.Def</code> . Once compiled, its output looks like this:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span> <span class="type">Ctypes</span></span><br><span class="line"><span class="keyword">let</span> lift x = x</span><br><span class="line"><span class="keyword">open</span> <span class="type">Ctypes_static</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> field : <span class="keyword">type</span> t a. t typ -&gt; <span class="built_in">string</span> -&gt; a typ -&gt; (a, t) field =</span><br><span class="line"> <span class="keyword">fun</span> s fname ftype -&gt; <span class="keyword">match</span> s, fname <span class="keyword">with</span></span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125;, _ -&gt;</span><br><span class="line"> <span class="keyword">let</span> &#123; ftype; foffset; fname &#125; = field ty fname ftype <span class="keyword">in</span></span><br><span class="line"> &#123; ftype; foffset; fname &#125;</span><br><span class="line"> | _ -&gt; failwith (<span class="string">&quot;Unexpected field &quot;</span>^ fname)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> seal : <span class="keyword">type</span> a. a typ -&gt; <span class="built_in">unit</span> = <span class="keyword">function</span></span><br><span class="line"> | <span class="type">Struct</span> &#123; tag; spec = <span class="type">Complete</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> tag)</span><br><span class="line"> | <span class="type">Union</span> &#123; utag; uspec = <span class="type">Some</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> utag)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125; -&gt; seal ty</span><br><span class="line"> | _ -&gt;</span><br><span class="line"> raise (<span class="type">Unsupported</span> <span class="string">&quot;Sealing a non-structured type&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="symbol">&#x27;a</span> const = <span class="symbol">&#x27;a</span></span><br><span class="line"><span class="keyword">let</span> constant (<span class="keyword">type</span> t) name (t : t typ) : t = <span class="keyword">match</span> t, name <span class="keyword">with</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_NUMERICSERV&quot;</span> -&gt;</span><br><span class="line"> <span class="number">8</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_NUMERICHOST&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_MAXHOST&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1025</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_MAXSERV&quot;</span> -&gt;</span><br><span class="line"> <span class="number">32</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCKLEN_T_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">4</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_STREAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_STREAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_DGRAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SA_FAMILY_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SA_DATA_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">14</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_UNSPEC&quot;</span> -&gt;</span><br><span class="line"> <span class="number">0</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_UNIX&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_INET6&quot;</span> -&gt;</span><br><span class="line"> <span class="number">30</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_INET&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | _, s -&gt; failwith (<span class="string">&quot;unmatched constant: &quot;</span>^ s)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> enum (<span class="keyword">type</span> a) name ?typedef ?unexpected (alist : (a * <span class="built_in">int64</span>) <span class="built_in">list</span>) =</span><br><span class="line"> <span class="keyword">match</span> name <span class="keyword">with</span></span><br><span class="line"> | s -&gt;</span><br><span class="line"> failwith (<span class="string">&quot;unmatched enum: &quot;</span>^ s)</span><br></pre></td></tr></table></figure>
+
+<p>The files used to describe how to build this binary using <code>dune</code> are located in a separate <code>[generator](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/generator)</code> directory. Here’s the entry to build this one:</p>
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">(executable</span><br><span class="line"> (name gen_constants_c)</span><br><span class="line"> (modules gen_constants_c)</span><br><span class="line"> (libraries sys-socket.constants ctypes.stubs))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_constants.c)</span><br><span class="line"> (deps (:gen ./gen_constants_c.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_constants_c)</span><br><span class="line"> (deps (:c_code ./gen_constants.c))</span><br><span class="line"> (action (run %&#123;ocaml-config:c_compiler&#125; -I %&#123;lib:ctypes:&#125; -I %&#123;ocaml-config:standard_library&#125; -o %&#123;targets&#125; %&#123;c_code&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>This executable is compiled during the next phase. Let’s move into it now!</p>
+<h2 id="Types-pass"><a href="#Types-pass" class="headerlink" title="Types pass"></a>Types pass</h2><p>During that phase, we use the constants exported during the previous phase to describe the various C structures and types. This is by far the most complex part of the code, making use of first-class modules and several OCaml tricks.</p>
+<p>First, let’s look at how we tell <code>dune</code> that we need to generate the <code>.ml</code> file exporting our required constants from the previous pass:</p>
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_constants.ml)</span><br><span class="line"> (deps (:exec ../generator/exec.sh)</span><br><span class="line"> (:gen ../generator/gen_constants_c))</span><br><span class="line"> (action (with-stdout-to %&#123;targets&#125;</span><br><span class="line"> (system &quot;%&#123;exec&#125; %&#123;ocaml-config:system&#125; %&#123;gen&#125;&quot;))))</span><br></pre></td></tr></table></figure>
+
+<p>With only this information, if the code refers to a <code>Sys_socket_generated_constants</code> module, <code>dune</code> will know that this module needs to be generated and how to do it. We will explain later the use of the <code>exec.sh</code> wrapper here.</p>
+<p>Now that we can make use of the exported constants in our OCaml code, let’s see how we define the <code>Socklen</code> module, exporting abstract types and interface to use <code>socklen_t</code> integers:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="type">Constants</span> = <span class="type">Sys_socket_constants</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_constants</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="keyword">type</span> <span class="type">Socklen</span> = <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> socklen</span><br><span class="line"> <span class="keyword">val</span> socklen_t : socklen <span class="type">S</span>.typ</span><br><span class="line"> <span class="keyword">val</span> int_of_socklen : socklen -&gt; <span class="built_in">int</span></span><br><span class="line"> <span class="keyword">val</span> socklen_of_int : <span class="built_in">int</span> -&gt; socklen</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> socklen : (<span class="keyword">module</span> <span class="type">Socklen</span>) =</span><br><span class="line"> <span class="keyword">match</span> <span class="type">Constants</span>.socklen_t_len <span class="keyword">with</span></span><br><span class="line"> | <span class="number">4</span> -&gt; (<span class="keyword">module</span> <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> socklen = <span class="type">Unsigned</span>.uint32</span><br><span class="line"> <span class="keyword">let</span> socklen_t = <span class="type">S</span>.uint32_t</span><br><span class="line"> <span class="keyword">let</span> int_of_socklen = <span class="type">Unsigned</span>.<span class="type">UInt32</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> socklen_of_int = <span class="type">Unsigned</span>.<span class="type">UInt32</span>.of_int</span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line"> | <span class="number">8</span> -&gt; (<span class="keyword">module</span> <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> socklen = <span class="type">Unsigned</span>.uint64</span><br><span class="line"> <span class="keyword">let</span> socklen_t = <span class="type">S</span>.uint64_t</span><br><span class="line"> <span class="keyword">let</span> int_of_socklen = <span class="type">Unsigned</span>.<span class="type">UInt64</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> socklen_of_int = <span class="type">Unsigned</span>.<span class="type">UInt64</span>.of_int</span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line"> | _ -&gt; <span class="keyword">assert</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Socklen</span> = (<span class="keyword">val</span> socklen : <span class="type">Socklen</span>)</span><br></pre></td></tr></table></figure>
+
+<p>As you can see, we make use of first-order modules and the size of the <code>socklen_t</code> integer to define the right API for the compiling host. Now let’s see how we define the <code>sockaddr</code> interface:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="keyword">type</span> <span class="type">SaFamily</span> = <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> sa_family</span><br><span class="line"> <span class="keyword">val</span> int_of_sa_family : sa_family -&gt; <span class="built_in">int</span></span><br><span class="line"> <span class="keyword">val</span> sa_family_of_int : <span class="built_in">int</span> -&gt; sa_family</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">module</span> <span class="type">T</span> : <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">val</span> t : sa_family <span class="type">S</span>.typ</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> saFamily : (<span class="keyword">module</span> <span class="type">SaFamily</span>) =</span><br><span class="line"> <span class="keyword">match</span> <span class="type">Constants</span>.sa_family_len <span class="keyword">with</span></span><br><span class="line"> | <span class="number">1</span> -&gt; (<span class="keyword">module</span> <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> sa_family = <span class="type">Unsigned</span>.uint8</span><br><span class="line"> <span class="keyword">let</span> int_of_sa_family = <span class="type">Unsigned</span>.<span class="type">UInt8</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> sa_family_of_int = <span class="type">Unsigned</span>.<span class="type">UInt8</span>.of_int </span><br><span class="line"> <span class="keyword">module</span> <span class="type">T</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">let</span> t = <span class="type">S</span>.uint8_t</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">SaFamily</span> = (<span class="keyword">val</span> saFamily : <span class="type">SaFamily</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Constants</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Socklen</span>(<span class="type">S</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">include</span> <span class="type">SaFamily</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">SaFamilyT</span> = <span class="type">SaFamily</span>.<span class="type">T</span>(<span class="type">S</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> sa_family_t = <span class="type">S</span>.typedef <span class="type">SaFamilyT</span>.t <span class="string">&quot;sa_family_t&quot;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">Sockaddr</span> = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> t = <span class="built_in">unit</span></span><br><span class="line"> <span class="keyword">let</span> t = <span class="type">S</span>.structure <span class="string">&quot;sockaddr&quot;</span></span><br><span class="line"> <span class="keyword">let</span> sa_family = <span class="type">S</span>.field t <span class="string">&quot;sa_family&quot;</span> sa_family_t</span><br><span class="line"> <span class="keyword">let</span> sa_data = <span class="type">S</span>.field t <span class="string">&quot;sa_data&quot;</span> (<span class="type">S</span>.<span class="built_in">array</span> sa_data_len <span class="type">S</span>.<span class="built_in">char</span>)</span><br><span class="line"> <span class="keyword">let</span> <span class="literal">()</span> = <span class="type">S</span>.seal t</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> </span><br><span class="line"> ...</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>Here, too, we make use of the size of <code>sa_family</code> as exported previously to define the right structure fields.</p>
+<p>Next step, we need to compile this interface again to export the right offset for the various structures that have been defined. That’s <code>dune</code>’s job again!</p>
+<p>First, the generator code:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;sys/un.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netinet/in.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.<span class="type">Types</span>.write_c format (<span class="keyword">module</span> <span class="type">Sys_socket_types</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>And the build instructions:</p>
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">(executable</span><br><span class="line"> (name gen_types_c)</span><br><span class="line"> (modules gen_types_c)</span><br><span class="line"> (libraries sys-socket.types ctypes.stubs))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_types.c)</span><br><span class="line"> (deps (:gen ./gen_types_c.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_types_c)</span><br><span class="line"> (deps (:c_code ./gen_types.c))</span><br><span class="line"> (action (run %&#123;ocaml-config:c_compiler&#125; -I %&#123;lib:ctypes:&#125; -I %&#123;ocaml-config:standard_library&#125; -o %&#123;targets&#125; %&#123;c_code&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>Once, compiled, the exported <code>.ml</code> looks like this:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">include</span> <span class="type">Ctypes</span></span><br><span class="line"><span class="keyword">let</span> lift x = x</span><br><span class="line"><span class="keyword">open</span> <span class="type">Ctypes_static</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> field : <span class="keyword">type</span> t a. t typ -&gt; <span class="built_in">string</span> -&gt; a typ -&gt; (a, t) field =</span><br><span class="line"> <span class="keyword">fun</span> s fname ftype -&gt; <span class="keyword">match</span> s, fname <span class="keyword">with</span></span><br><span class="line">...</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>&#125; <span class="keyword">as</span> s&#x27;), <span class="string">&quot;sa_data&quot;</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> f = &#123;ftype; fname; foffset = <span class="number">2</span>&#125; <span class="keyword">in</span></span><br><span class="line"> (s&#x27;.fields &lt;- <span class="type">BoxedField</span> f :: s&#x27;.fields; f)</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>&#125; <span class="keyword">as</span> s&#x27;), <span class="string">&quot;sa_family&quot;</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> f = &#123;ftype; fname; foffset = <span class="number">1</span>&#125; <span class="keyword">in</span></span><br><span class="line"> (s&#x27;.fields &lt;- <span class="type">BoxedField</span> f :: s&#x27;.fields; f)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125;, _ -&gt;</span><br><span class="line"> <span class="keyword">let</span> &#123; ftype; foffset; fname &#125; = field ty fname ftype <span class="keyword">in</span></span><br><span class="line"> &#123; ftype; foffset; fname &#125;</span><br><span class="line"> | _ -&gt; failwith (<span class="string">&quot;Unexpected field &quot;</span>^ fname)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> seal : <span class="keyword">type</span> a. a typ -&gt; <span class="built_in">unit</span> = <span class="keyword">function</span></span><br><span class="line">...</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr_storage&quot;</span>; spec = <span class="type">Incomplete</span> _ &#125; <span class="keyword">as</span> s&#x27;) -&gt;</span><br><span class="line"> s&#x27;.spec &lt;- <span class="type">Complete</span> &#123; size = <span class="number">128</span>; align = <span class="number">8</span> &#125;</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>; spec = <span class="type">Incomplete</span> _ &#125; <span class="keyword">as</span> s&#x27;) -&gt;</span><br><span class="line"> s&#x27;.spec &lt;- <span class="type">Complete</span> &#123; size = <span class="number">16</span>; align = <span class="number">1</span> &#125;</span><br><span class="line"> | <span class="type">Struct</span> &#123; tag; spec = <span class="type">Complete</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> tag)</span><br><span class="line"> | <span class="type">Union</span> &#123; utag; uspec = <span class="type">Some</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> utag)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125; -&gt; seal ty</span><br><span class="line"> | _ -&gt;</span><br><span class="line"> raise (<span class="type">Unsupported</span> <span class="string">&quot;Sealing a non-structured type&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="symbol">&#x27;a</span> const = <span class="symbol">&#x27;a</span></span><br><span class="line"><span class="keyword">let</span> constant (<span class="keyword">type</span> t) name (t : t typ) : t = <span class="keyword">match</span> t, name <span class="keyword">with</span></span><br><span class="line"> | _, s -&gt; failwith (<span class="string">&quot;unmatched constant: &quot;</span>^ s)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> enum (<span class="keyword">type</span> a) name ?typedef ?unexpected (alist : (a * <span class="built_in">int64</span>) <span class="built_in">list</span>) =</span><br><span class="line"> <span class="keyword">match</span> name <span class="keyword">with</span></span><br><span class="line"> | s -&gt;</span><br><span class="line"> failwith (<span class="string">&quot;unmatched enum: &quot;</span>^ s)</span><br></pre></td></tr></table></figure>
+
+<p>As you can see, this exports all the offsets required to access the fields inside a <code>sockaddr_t</code> structure. We’re now ready to move to the final stage, which is the actual binding stubs!</p>
+<h2 id="Binding-stubs"><a href="#Binding-stubs" class="headerlink" title="Binding stubs"></a>Binding stubs</h2><p>First step in this pass, just like with the previous ones, we need to configure <code>dune</code> to be able to build the exported <code>.ml</code> code from the <code>types</code> pass:</p>
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_types.ml)</span><br><span class="line"> (deps (:exec ../generator/exec.sh)</span><br><span class="line"> (:gen ../generator/gen_types_c))</span><br><span class="line"> (action (with-stdout-to %&#123;targets&#125;</span><br><span class="line"> (system &quot;%&#123;exec&#125; %&#123;ocaml-config:system&#125; %&#123;gen&#125;&quot;))))</span><br></pre></td></tr></table></figure>
+
+<p>And we can now define the proper bindings. Here’s how it looks like:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">F</span> : <span class="type">Cstubs</span>.<span class="type">FOREIGN</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">open</span> <span class="type">F</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">Types</span> = <span class="type">Sys_socket_types</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_types</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">open</span> <span class="type">Types</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> getnameinfo = foreign <span class="string">&quot;getnameinfo&quot;</span> (ptr sockaddr_t @-&gt; socklen_t @-&gt; ptr <span class="built_in">char</span> @-&gt; socklen_t @-&gt; ptr <span class="built_in">char</span> @-&gt; socklen_t @-&gt; <span class="built_in">int</span> @-&gt; (returning <span class="built_in">int</span>))</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>As you can see, we’re exporting the <code>getnameinfo</code> function, taking various arguments, including a pointer to a <code>sockaddr_t</code> structure and a couple of <code>socklen_t</code> integers, making use of all the various data types and structures previously defined. The exact specifications of this function can be found <a target="_blank" rel="noopener" href="https://pubs.opengroup.org/onlinepubs/009695399/functions/getnameinfo.html">here</a>. We can now define out top-level API..</p>
+<h2 id="Final-API"><a href="#Final-API" class="headerlink" title="Final API"></a>Final API</h2><p>Building upon the previous modules, we export various OCaml idiomatic APIs that the binding user can now use to build new bindings against the <code>socket.h</code> APIs.</p>
+<p>Just like with the previous steps, first we need to configure the build system:</p>
+<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_stubs.ml)</span><br><span class="line"> (deps (:gen ./generator/gen_stubs.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; ml %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_stubs.c)</span><br><span class="line"> (deps (:gen ./generator/gen_stubs.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; c %&#123;targets&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>This time, we need <code>ocaml-ctypes</code> to generate two compilation units: a <code>.ml</code> file describing the API exported during the <code>stubs</code> phase, as well as the C code to glue it with the C APIs. Here’s the code for that generator:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netinet/in.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;arpa/inet.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#include &lt;string.h&gt;</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> mode = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">2</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> fn =</span><br><span class="line"> <span class="keyword">match</span> mode <span class="keyword">with</span></span><br><span class="line"> | <span class="string">&quot;ml&quot;</span> -&gt; <span class="type">Cstubs</span>.write_ml</span><br><span class="line"> | <span class="string">&quot;c&quot;</span> -&gt;</span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.write_c</span><br><span class="line"> | _ -&gt; <span class="keyword">assert</span> <span class="literal">false</span></span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> fn ~concurrency:<span class="type">Cstubs</span>.unlocked format ~prefix:<span class="string">&quot;sys_socket&quot;</span> (<span class="keyword">module</span> <span class="type">Sys_socket_stubs</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>The exported <code>.ml</code> and <code>.c</code> files are omitted here for simplicity but the reader can generated them themselves from the <code>[ocaml-sys-socket](https://github.com/toots/ocaml-sys-socket)</code> repository if they are curious about their actual content.</p>
+<p>We can now export our top-level API:</p>
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="type">Sys_socket_types</span>.<span class="type">SaFamily</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="type">Sys_socket_stubs</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_stubs</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> socklen = <span class="type">Types</span>.socklen</span><br><span class="line"><span class="keyword">let</span> socklen_t = <span class="type">Types</span>.socklen_t</span><br><span class="line"><span class="keyword">let</span> int_of_socklen = <span class="type">Types</span>.int_of_socklen</span><br><span class="line"><span class="keyword">let</span> socklen_of_int = <span class="type">Types</span>.socklen_of_int</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Sockaddr</span> = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Types</span>.<span class="type">Sockaddr</span></span><br><span class="line"> <span class="keyword">let</span> from_sockaddr_storage = from_sockaddr_storage t</span><br><span class="line"> <span class="keyword">let</span> sa_data_len = <span class="type">Types</span>.sa_data_len</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> getnameinfo sockaddr_ptr =</span><br><span class="line"> <span class="keyword">let</span> maxhost = <span class="type">Types</span>.ni_maxhost <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> s = allocate_n <span class="built_in">char</span> ~count:maxhost <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> maxserv = <span class="type">Types</span>.ni_maxserv <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> p = allocate_n <span class="built_in">char</span> ~count:maxserv <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">match</span> getnameinfo sockaddr_ptr (socklen_of_int (sizeof sockaddr_t))</span><br><span class="line"> s (socklen_of_int maxhost) </span><br><span class="line"> p (socklen_of_int maxserv)</span><br><span class="line"> (<span class="type">Types</span>.ni_numerichost <span class="keyword">lor</span></span><br><span class="line"> <span class="type">Types</span>.ni_numericserv) <span class="keyword">with</span></span><br><span class="line"> | <span class="number">0</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> host =</span><br><span class="line"> <span class="keyword">let</span> length =</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">Size_t</span>.to_int</span><br><span class="line"> (strnlen s (<span class="type">Unsigned</span>.<span class="type">Size_t</span>.of_int maxhost))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> string_from_ptr s ~length</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> port =</span><br><span class="line"> <span class="keyword">let</span> length =</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">Size_t</span>.to_int</span><br><span class="line"> (strnlen p (<span class="type">Unsigned</span>.<span class="type">Size_t</span>.of_int maxserv))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> port =</span><br><span class="line"> string_from_ptr p ~length</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> int_of_string port</span><br><span class="line"> <span class="keyword">with</span> _ -&gt;</span><br><span class="line"> <span class="keyword">match</span> getservbyname p null <span class="keyword">with</span></span><br><span class="line"> | ptr <span class="keyword">when</span> is_null ptr -&gt; failwith <span class="string">&quot;getnameinfo&quot;</span></span><br><span class="line"> | ptr -&gt;</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">UInt16</span>.to_int</span><br><span class="line"> (ntohs (!@ (ptr |-&gt; <span class="type">Types</span>.<span class="type">Servent</span>.s_port)))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> host, port</span><br><span class="line"> | _ -&gt; failwith <span class="string">&quot;getnameinfo&quot;</span></span><br><span class="line"></span><br><span class="line">...</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="comment">(** Ctypes routines for C type socklen_t. *)</span></span><br><span class="line"><span class="keyword">type</span> socklen</span><br><span class="line"><span class="keyword">val</span> socklen_t : socklen typ</span><br><span class="line"><span class="keyword">val</span> int_of_socklen : socklen -&gt; <span class="built_in">int</span></span><br><span class="line"><span class="keyword">val</span> socklen_of_int : <span class="built_in">int</span> -&gt; socklen</span><br><span class="line"></span><br><span class="line"><span class="comment">(** Generic sockaddr_t structure. *)</span></span><br><span class="line"><span class="keyword">module</span> <span class="type">Sockaddr</span> : <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> t</span><br><span class="line"> <span class="keyword">val</span> t : t structure typ</span><br><span class="line"> <span class="keyword">val</span> sa_family : (sa_family, t structure) field</span><br><span class="line"> <span class="keyword">val</span> sa_data : (<span class="built_in">char</span> carray, t structure) field</span><br><span class="line"> <span class="keyword">val</span> sa_data_len : <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">val</span> from_sockaddr_storage : <span class="type">SockaddrStorage</span>.t structure ptr -&gt; t structure ptr</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">(** IP address conversion functions. *)</span></span><br><span class="line"><span class="keyword">val</span> getnameinfo : sockaddr ptr -&gt; <span class="built_in">string</span> * <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line">...</span><br></pre></td></tr></table></figure>
+
+<p>That’s it! We now have <code>ocaml-ctypes</code> specific data types and structures that can be used to interface with the host’s native <code>socket.h</code> APIs. Note that we also worked on top of the original low-level binding to <code>getnameinfo</code> to export a higher-level function more idiomatic to the OCaml language.</p>
+<h1 id="Lagniappe-cross-compilation-to-Windows"><a href="#Lagniappe-cross-compilation-to-Windows" class="headerlink" title="Lagniappe: cross-compilation to Windows"></a>Lagniappe: cross-compilation to Windows</h1><p>On windows platforms, <code>liquidsoap</code> is compiled using <code>[ocaml-cross-windows](https://github.com/ocaml-cross/opam-cross-windows)</code> and, since windows does have compatible socket APIs, we wanted to also look at cross-compiling for the windows target, which is where we hit a snag on the current <code>dune</code> support.</p>
+<p>The problem is that, at each intermediary steps, in the case of a cross-compilation, the compiled binaries need to use the target’s OS headers and not the host’s headers, otherwise we end up using offsets specific to e.g. Debian but for a windows binary.</p>
+<p>In this case, this means that the compiled <code>.exe</code> binaries need to be windows binaries and that we need to execute them as windows native binaries, using <code>[wine](https://www.winehq.org/)</code> .</p>
+<p><code>dune</code> has a truly amazing <a target="_blank" rel="noopener" href="https://dune.readthedocs.io/en/latest/cross-compilation.html">support for cross-compiling</a>, which we do not cover here, but, unfortunately, its primitives for building and executing binaries do not yet cover this use case. Thus we had to trick it into compiling things the way we wanted to do, which why we are using the <code>exec.sh</code> wrapper. Here’s its code:</p>
+<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/sh</span></span><br><span class="line"></span><br><span class="line">SYSTEM=<span class="variable">$1</span></span><br><span class="line">CMD=<span class="variable">$2</span></span><br><span class="line">ARG=<span class="variable">$3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">test</span> <span class="string">&quot;<span class="variable">$&#123;SYSTEM&#125;</span>&quot;</span> = <span class="string">&quot;mingw&quot;</span>; <span class="keyword">then</span></span><br><span class="line"> wine <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br><span class="line"><span class="keyword">elif</span> <span class="built_in">test</span> <span class="string">&quot;<span class="variable">$&#123;SYSTEM&#125;</span>&quot;</span> = <span class="string">&quot;mingw64&quot;</span>; <span class="keyword">then</span></span><br><span class="line"> wine64 <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"> <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br></pre></td></tr></table></figure>
+
+<p>Now, you can go back to the previous <code>dune</code> files and see how this wrapper allows to execute binaries according to the system that the corresponding <code>ocamlopt</code> compiler has been configured to build for.</p>
+<h1 id="Conclusion"><a href="#Conclusion" class="headerlink" title="Conclusion"></a>Conclusion</h1><p>It’s been a fun time working on this binding! It’s amazing to see the level of details that can be built through <code>ocaml-ctypes</code> using their provided primitives. Ultimately, the binding is very clean and elegant, with very few low-level assumptions.</p>
+<p>Likewise, the simplicity and power of the <code>dune</code> build system makes this very fluid to build. Without it, each of the described steps above would have been much more painful to execute and compile.</p>
+<p>[1]: My bet is that, at the time the POSIX specifications were being written, there we already several inconsistent <code>socket.h</code> headers out in the wild among the various historical UNIX flavors..</p>
+
+</div>
+
+<script>
+ window.onload = detectors();
+</script>
+ <div class="post-footer">
+ <div class="h-line-primary"></div>
+ <nav class="post-nav">
+ <div class="prev-item">
+
+ <div class="icon arrow-left"></div>
+ <div class="post-link">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">Prev</a>
+ </div>
+
+ </div>
+ <div class="next-item">
+
+ <div class="icon arrow-right"></div>
+ <div class="post-link">
+ <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">Next</a>
+ </div>
+
+ </div>
+ </nav>
+</div>
+
+
+ <div class="post-comment">
+
+
+
+
+
+
+
+</div>
+
+
+</article>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/2024/09/15/肩周炎和肩袖损伤的区别/index.html b/2024/09/15/肩周炎和肩袖损伤的区别/index.html
new file mode 100644
index 00000000..47941de8
--- /dev/null
+++ b/2024/09/15/肩周炎和肩袖损伤的区别/index.html
@@ -0,0 +1,282 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>肩周炎和肩袖损伤的区别 | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <article id="post">
+
+
+ <div class="post-head">
+ <div class="post-info">
+ <div class="tag-list">
+
+
+ <span class="post-tag">
+ <a href="/tags/Medicine/">
+ Medicine
+ </a>
+ </span>
+
+ <span class="post-tag">
+ <a href="/tags/Life/">
+ Life
+ </a>
+ </span>
+
+
+ </div>
+ <div class="post-title">
+
+
+ 肩周炎和肩袖损伤的区别
+
+
+ </div>
+ <span class="post-date">
+ Sep 15, 2024
+ </span>
+ </div>
+ <div class="post-img">
+
+ <div class="h-line-primary"></div>
+
+ </div>
+</div>
+ <div class="post-content">
+ <p>在肩痛患者中,只有2%~5%是肩周炎,肩袖损伤更为常见,占30%~40%。</p>
+<p>肩周炎和肩袖损伤都是临床上常见的疾病。很多肩痛患者认为自己患有肩周炎,坚持做肩关节活动训练,但一直没有缓解,且逐渐加重,甚至影响了睡眠和生活,遂至医院就诊,经过影像学检查确诊为肩袖损伤。这是因为肩周炎和肩袖损伤均可引起肩痛,严重时均可出现夜间疼痛,甚至影响睡眠,症状相似,故极易混淆。</p>
+<p>肩周炎是肩关节冻结、活动受限,遇风、寒冷加重,是肩周软组织(包括肩周肌、肌腱、滑囊和关节囊等)病变引起的以肩关节疼痛和功能障碍为特征的疾病。</p>
+<p>肩袖损伤是由退行性病变或外力等导致肩袖的4块肌肉、肌腱发生病变,进而导致肩关节局部疼痛、活动受限的疾病。</p>
+<p>许多肩袖损伤患者无明确的外伤史,而是由长期做过顶运动、提重物或上肢长期固定于一个姿势引起的。</p>
+<ul>
+<li><p>肩周炎的疼痛范围广,涉及整个肩关节,肩袖损伤引起的疼痛多出现在肩前方、外上方</p>
+</li>
+<li><p>肩周炎的压痛点多而广,肩袖损的伤压痛点多出现在肩前方、上方及肩胛骨外侧缘。</p>
+</li>
+<li><p>肩周炎患者对气候变化较为敏感,肩袖损伤患者对气候变化不敏感,对劳累、提重物及做过顶运动较为敏感。</p>
+</li>
+<li><p>肩周炎患者活动受限范围广,肩袖损伤患者多以肩关节外展活动受限为主,同时伴有外展无力。</p>
+</li>
+<li><p>肩周炎患者进行上举过顶运动训练后活动范围会好转,症状会减轻;而肩袖损伤患者进行上举过顶运动训练后疼痛加重。</p>
+</li>
+</ul>
+
+</div>
+
+<script>
+ window.onload = detectors();
+</script>
+ <div class="post-footer">
+ <div class="h-line-primary"></div>
+ <nav class="post-nav">
+ <div class="prev-item">
+
+ </div>
+ <div class="next-item">
+
+ <div class="icon arrow-right"></div>
+ <div class="post-link">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">Next</a>
+ </div>
+
+ </div>
+ </nav>
+</div>
+
+
+ <div class="post-comment">
+
+
+
+
+
+
+
+</div>
+
+
+</article>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/archives/2024/09/index.html b/archives/2024/09/index.html
index 60227b4d..ee952352 100644
--- a/archives/2024/09/index.html
+++ b/archives/2024/09/index.html
@@ -144,6 +144,42 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
+
+ 肩周炎和肩袖损伤的区别
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
+
+ Advanced C binding using ocaml-ctypes and dune
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
Functional Reactive Programming in F#
diff --git a/archives/2024/index.html b/archives/2024/index.html
index cafcdfa3..b392b3b3 100644
--- a/archives/2024/index.html
+++ b/archives/2024/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
- Functional Reactive Programming in F#
+ 肩周炎和肩袖损伤的区别
</a>
</div>
- <span class="post-date">Sep 12, 2024</span>
+ <span class="post-date">Sep 15, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
- 二〇二四年九月十二日
+ Advanced C binding using ocaml-ctypes and dune
</a>
</div>
- <span class="post-date">Sep 12, 2024</span>
+ <span class="post-date">Sep 15, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/08/%E4%B8%AD%E8%80%81%E5%B9%B4%E4%BA%BA%E6%B2%89%E8%BF%B7%E6%89%8B%E6%9C%BA%E7%9A%84%E9%97%AE%E9%A2%98/">
+ <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
- 中老年人沉迷手机的问题
+ Functional Reactive Programming in F#
</a>
</div>
- <span class="post-date">Sep 8, 2024</span>
+ <span class="post-date">Sep 12, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/07/%E7%BB%99%E5%AD%A9%E5%AD%90%E4%BB%AC%E7%9A%84%E8%AF%9D/">
+ <a href="/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 给孩子们的话
+ 二〇二四年九月十二日
</a>
</div>
- <span class="post-date">Sep 7, 2024</span>
+ <span class="post-date">Sep 12, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2024/09/08/%E4%B8%AD%E8%80%81%E5%B9%B4%E4%BA%BA%E6%B2%89%E8%BF%B7%E6%89%8B%E6%9C%BA%E7%9A%84%E9%97%AE%E9%A2%98/">
- 二〇二四年九月一日
+ 中老年人沉迷手机的问题
</a>
</div>
- <span class="post-date">Sep 1, 2024</span>
+ <span class="post-date">Sep 8, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
+ <a href="/2024/09/07/%E7%BB%99%E5%AD%A9%E5%AD%90%E4%BB%AC%E7%9A%84%E8%AF%9D/">
- 藿香正气水和藿香正气口服液的区别
+ 给孩子们的话
</a>
</div>
- <span class="post-date">Sep 1, 2024</span>
+ <span class="post-date">Sep 7, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/08/12/%E7%9B%B4%E7%B3%BB%E8%A1%80%E4%BA%B2%E4%B9%8B%E9%97%B4%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%BE%93%E8%A1%80/">
+ <a href="/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/">
- 直系血亲之间不能直接输血
+ 二〇二四年九月一日
</a>
</div>
- <span class="post-date">Aug 12, 2024</span>
+ <span class="post-date">Sep 1, 2024</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
- 二〇二四年八月一日
+ 藿香正气水和藿香正气口服液的区别
</a>
</div>
- <span class="post-date">Aug 2, 2024</span>
+ <span class="post-date">Sep 1, 2024</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/23/OCaml-News-2024-6/">
+ <a href="/2024/08/12/%E7%9B%B4%E7%B3%BB%E8%A1%80%E4%BA%B2%E4%B9%8B%E9%97%B4%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%BE%93%E8%A1%80/">
- OCaml News 2024-6
+ 直系血亲之间不能直接输血
</a>
</div>
- <span class="post-date">Jul 23, 2024</span>
+ <span class="post-date">Aug 12, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/09/%E7%A5%9E%E7%BB%8F%E7%B3%BB%E7%BB%9F%E9%87%8D%E7%82%B9/">
+ <a href="/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
- 内护神经系统重点考点
+ 二〇二四年八月一日
</a>
</div>
- <span class="post-date">Jul 9, 2024</span>
+ <span class="post-date">Aug 2, 2024</span>
</div>
diff --git a/archives/2024/page/2/index.html b/archives/2024/page/2/index.html
index 0dc338e1..0672183a 100644
--- a/archives/2024/page/2/index.html
+++ b/archives/2024/page/2/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/01/OCaml-News-2024-4/">
+ <a href="/2024/07/23/OCaml-News-2024-6/">
- OCaml News 2024-4
+ OCaml News 2024-6
</a>
</div>
- <span class="post-date">Jul 1, 2024</span>
+ <span class="post-date">Jul 23, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
+ <a href="/2024/07/09/%E7%A5%9E%E7%BB%8F%E7%B3%BB%E7%BB%9F%E9%87%8D%E7%82%B9/">
- 二〇二四年六月二十七日
+ 内护神经系统重点考点
</a>
</div>
- <span class="post-date">Jun 27, 2024</span>
+ <span class="post-date">Jul 9, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/27/OCaml-News-2024-5/">
+ <a href="/2024/07/01/OCaml-News-2024-4/">
- OCaml News 2024-5
+ OCaml News 2024-4
</a>
</div>
- <span class="post-date">Jun 27, 2024</span>
+ <span class="post-date">Jul 1, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
+ <a href="/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
- .NET AOT 下的 F# 命令行参数解析库选择
+ 二〇二四年六月二十七日
</a>
</div>
- <span class="post-date">Jun 6, 2024</span>
+ <span class="post-date">Jun 27, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/20/Rescript-genType-import-%E9%97%AE%E9%A2%98/">
+ <a href="/2024/06/27/OCaml-News-2024-5/">
- Rescript @genType import 问题
+ OCaml News 2024-5
</a>
</div>
- <span class="post-date">May 20, 2024</span>
+ <span class="post-date">Jun 27, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
+ <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
- 二〇二四年五月十六日
+ .NET AOT 下的 F# 命令行参数解析库选择
</a>
</div>
- <span class="post-date">May 16, 2024</span>
+ <span class="post-date">Jun 6, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/13/%E7%BB%99%E5%B0%B8%E4%BD%93%E4%B8%8A-ECMO-%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3/">
+ <a href="/2024/05/20/Rescript-genType-import-%E9%97%AE%E9%A2%98/">
- 给尸体上 ECMO 并维持心跳
+ Rescript @genType import 问题
</a>
</div>
- <span class="post-date">May 13, 2024</span>
+ <span class="post-date">May 20, 2024</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%83%E6%97%A5/">
+ <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
- 二〇二四年五月七日
+ 二〇二四年五月十六日
</a>
</div>
- <span class="post-date">May 7, 2024</span>
+ <span class="post-date">May 16, 2024</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/04/08/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%9B%9B%E6%9C%88%E5%85%AB%E6%97%A5/">
+ <a href="/2024/05/13/%E7%BB%99%E5%B0%B8%E4%BD%93%E4%B8%8A-ECMO-%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3/">
- 二〇二四年四月八日
+ 给尸体上 ECMO 并维持心跳
</a>
</div>
- <span class="post-date">Apr 8, 2024</span>
+ <span class="post-date">May 13, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/04/03/shadow-cljs-proxy/">
+ <a href="/2024/05/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%83%E6%97%A5/">
- shadow-cljs 怎么设置代理
+ 二〇二四年五月七日
</a>
</div>
- <span class="post-date">Apr 3, 2024</span>
+ <span class="post-date">May 7, 2024</span>
</div>
diff --git a/archives/2024/page/3/index.html b/archives/2024/page/3/index.html
index 68754e76..da07927a 100644
--- a/archives/2024/page/3/index.html
+++ b/archives/2024/page/3/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/04/08/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%9B%9B%E6%9C%88%E5%85%AB%E6%97%A5/">
- 二〇二四年三月二十二日
+ 二〇二四年四月八日
</a>
</div>
- <span class="post-date">Mar 22, 2024</span>
+ <span class="post-date">Apr 8, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/03/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/04/03/shadow-cljs-proxy/">
- 二〇二四年三月十二日
+ shadow-cljs 怎么设置代理
</a>
</div>
- <span class="post-date">Mar 12, 2024</span>
+ <span class="post-date">Apr 3, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/02/26/OCaml-News-2024-3/">
+ <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
- OCaml News 2024-3
+ 二〇二四年三月二十二日
</a>
</div>
- <span class="post-date">Feb 26, 2024</span>
+ <span class="post-date">Mar 22, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/02/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%83%E6%97%A5/">
+ <a href="/2024/03/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 二〇二四年二月七日
+ 二〇二四年三月十二日
</a>
</div>
- <span class="post-date">Feb 7, 2024</span>
+ <span class="post-date">Mar 12, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/25/%E6%80%A5%E8%AF%8A%E4%B8%8E%E7%81%BE%E9%9A%BE%E5%8C%BB%E5%AD%A6-%E7%83%A7%E4%BC%A4/">
+ <a href="/2024/02/26/OCaml-News-2024-3/">
- 急诊与灾难医学--烧伤
+ OCaml News 2024-3
</a>
</div>
- <span class="post-date">Jan 25, 2024</span>
+ <span class="post-date">Feb 26, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/G-Machine/">
+ <a href="/2024/02/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%83%E6%97%A5/">
- G-Machine
+ 二〇二四年二月七日
</a>
</div>
- <span class="post-date">Jan 23, 2024</span>
+ <span class="post-date">Feb 7, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
+ <a href="/2024/01/25/%E6%80%A5%E8%AF%8A%E4%B8%8E%E7%81%BE%E9%9A%BE%E5%8C%BB%E5%AD%A6-%E7%83%A7%E4%BC%A4/">
- 慢性肺源性心脏病
+ 急诊与灾难医学--烧伤
</a>
</div>
- <span class="post-date">Jan 23, 2024</span>
+ <span class="post-date">Jan 25, 2024</span>
</div>
@@ -270,9 +270,9 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/">
+ <a href="/2024/01/23/G-Machine/">
- 二〇二四年一月二十三日
+ G-Machine
</a>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/22/Rescript-React-Native/">
+ <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
- Rescript and React Native
+ 慢性肺源性心脏病
</a>
</div>
- <span class="post-date">Jan 22, 2024</span>
+ <span class="post-date">Jan 23, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/18/OCaml-News-2024-2/">
+ <a href="/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/">
- OCaml News 2024-2
+ 二〇二四年一月二十三日
</a>
</div>
- <span class="post-date">Jan 18, 2024</span>
+ <span class="post-date">Jan 23, 2024</span>
</div>
diff --git a/archives/2024/page/4/index.html b/archives/2024/page/4/index.html
index 2fc65e50..25dea745 100644
--- a/archives/2024/page/4/index.html
+++ b/archives/2024/page/4/index.html
@@ -144,6 +144,42 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/01/22/Rescript-React-Native/">
+
+ Rescript and React Native
+
+ </a>
+ </div>
+
+ <span class="post-date">Jan 22, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2024/01/18/OCaml-News-2024-2/">
+
+ OCaml News 2024-2
+
+ </a>
+ </div>
+
+ <span class="post-date">Jan 18, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/01/08/OCaml-News-2024-1/">
OCaml News 2024-1
diff --git a/archives/index.html b/archives/index.html
index 3597c87a..15360fcb 100644
--- a/archives/index.html
+++ b/archives/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
- Functional Reactive Programming in F#
+ 肩周炎和肩袖损伤的区别
</a>
</div>
- <span class="post-date">Sep 12, 2024</span>
+ <span class="post-date">Sep 15, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
- 二〇二四年九月十二日
+ Advanced C binding using ocaml-ctypes and dune
</a>
</div>
- <span class="post-date">Sep 12, 2024</span>
+ <span class="post-date">Sep 15, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/08/%E4%B8%AD%E8%80%81%E5%B9%B4%E4%BA%BA%E6%B2%89%E8%BF%B7%E6%89%8B%E6%9C%BA%E7%9A%84%E9%97%AE%E9%A2%98/">
+ <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
- 中老年人沉迷手机的问题
+ Functional Reactive Programming in F#
</a>
</div>
- <span class="post-date">Sep 8, 2024</span>
+ <span class="post-date">Sep 12, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/07/%E7%BB%99%E5%AD%A9%E5%AD%90%E4%BB%AC%E7%9A%84%E8%AF%9D/">
+ <a href="/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 给孩子们的话
+ 二〇二四年九月十二日
</a>
</div>
- <span class="post-date">Sep 7, 2024</span>
+ <span class="post-date">Sep 12, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2024/09/08/%E4%B8%AD%E8%80%81%E5%B9%B4%E4%BA%BA%E6%B2%89%E8%BF%B7%E6%89%8B%E6%9C%BA%E7%9A%84%E9%97%AE%E9%A2%98/">
- 二〇二四年九月一日
+ 中老年人沉迷手机的问题
</a>
</div>
- <span class="post-date">Sep 1, 2024</span>
+ <span class="post-date">Sep 8, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
+ <a href="/2024/09/07/%E7%BB%99%E5%AD%A9%E5%AD%90%E4%BB%AC%E7%9A%84%E8%AF%9D/">
- 藿香正气水和藿香正气口服液的区别
+ 给孩子们的话
</a>
</div>
- <span class="post-date">Sep 1, 2024</span>
+ <span class="post-date">Sep 7, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/08/12/%E7%9B%B4%E7%B3%BB%E8%A1%80%E4%BA%B2%E4%B9%8B%E9%97%B4%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%BE%93%E8%A1%80/">
+ <a href="/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/">
- 直系血亲之间不能直接输血
+ 二〇二四年九月一日
</a>
</div>
- <span class="post-date">Aug 12, 2024</span>
+ <span class="post-date">Sep 1, 2024</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
- 二〇二四年八月一日
+ 藿香正气水和藿香正气口服液的区别
</a>
</div>
- <span class="post-date">Aug 2, 2024</span>
+ <span class="post-date">Sep 1, 2024</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/23/OCaml-News-2024-6/">
+ <a href="/2024/08/12/%E7%9B%B4%E7%B3%BB%E8%A1%80%E4%BA%B2%E4%B9%8B%E9%97%B4%E4%B8%8D%E8%83%BD%E7%9B%B4%E6%8E%A5%E8%BE%93%E8%A1%80/">
- OCaml News 2024-6
+ 直系血亲之间不能直接输血
</a>
</div>
- <span class="post-date">Jul 23, 2024</span>
+ <span class="post-date">Aug 12, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/09/%E7%A5%9E%E7%BB%8F%E7%B3%BB%E7%BB%9F%E9%87%8D%E7%82%B9/">
+ <a href="/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
- 内护神经系统重点考点
+ 二〇二四年八月一日
</a>
</div>
- <span class="post-date">Jul 9, 2024</span>
+ <span class="post-date">Aug 2, 2024</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <span class="page-number current">1</span><a class="page-number" href="/archives/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <span class="page-number current">1</span><a class="page-number" href="/archives/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/10/index.html b/archives/page/10/index.html
index ca9a1c4d..265b8dd6 100644
--- a/archives/page/10/index.html
+++ b/archives/page/10/index.html
@@ -144,6 +144,42 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2022/09/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+
+ 二零二二年九月二十二日
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 22, 2022</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
+
+ 二零二二年八月二十一日
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 21, 2022</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2022/03/14/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E5%9B%9B%E6%97%A5/">
二零二二年三月十四日
@@ -285,30 +321,12 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2020/12/08/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E9%9B%B6%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E5%85%AB%E6%97%A5/">
-
- 二零二零年十二月八日
-
- </a>
- </div>
-
- <span class="post-date">Dec 8, 2020</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/9/">9</a><span class="page-number current">10</span>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/9/">9</a><span class="page-number current">10</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/11/index.html b/archives/page/11/index.html
new file mode 100644
index 00000000..a2165b41
--- /dev/null
+++ b/archives/page/11/index.html
@@ -0,0 +1,224 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>Archive | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <div class="post-list">
+
+
+
+
+
+
+ <div class="year-title">2020</div>
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2020/12/08/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E9%9B%B6%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E5%85%AB%E6%97%A5/">
+
+ 二零二零年十二月八日
+
+ </a>
+ </div>
+
+ <span class="post-date">Dec 8, 2020</span>
+ </div>
+
+
+ <div id="paginator">
+
+ <div class=paginator>
+ <div class="h-line-primary"></div>
+ <nav class="pagination">
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a><span class="page-number current">11</span>
+ </nav>
+ </div>
+
+ </div>
+</div>
+
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/archives/page/2/index.html b/archives/page/2/index.html
index 5cd05188..fbd7b523 100644
--- a/archives/page/2/index.html
+++ b/archives/page/2/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/07/01/OCaml-News-2024-4/">
+ <a href="/2024/07/23/OCaml-News-2024-6/">
- OCaml News 2024-4
+ OCaml News 2024-6
</a>
</div>
- <span class="post-date">Jul 1, 2024</span>
+ <span class="post-date">Jul 23, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
+ <a href="/2024/07/09/%E7%A5%9E%E7%BB%8F%E7%B3%BB%E7%BB%9F%E9%87%8D%E7%82%B9/">
- 二〇二四年六月二十七日
+ 内护神经系统重点考点
</a>
</div>
- <span class="post-date">Jun 27, 2024</span>
+ <span class="post-date">Jul 9, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/27/OCaml-News-2024-5/">
+ <a href="/2024/07/01/OCaml-News-2024-4/">
- OCaml News 2024-5
+ OCaml News 2024-4
</a>
</div>
- <span class="post-date">Jun 27, 2024</span>
+ <span class="post-date">Jul 1, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
+ <a href="/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
- .NET AOT 下的 F# 命令行参数解析库选择
+ 二〇二四年六月二十七日
</a>
</div>
- <span class="post-date">Jun 6, 2024</span>
+ <span class="post-date">Jun 27, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/20/Rescript-genType-import-%E9%97%AE%E9%A2%98/">
+ <a href="/2024/06/27/OCaml-News-2024-5/">
- Rescript @genType import 问题
+ OCaml News 2024-5
</a>
</div>
- <span class="post-date">May 20, 2024</span>
+ <span class="post-date">Jun 27, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
+ <a href="/2024/06/06/NET-AOT-%E4%B8%8B%E7%9A%84-F-%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E8%A7%A3%E6%9E%90%E5%BA%93%E9%80%89%E6%8B%A9/">
- 二〇二四年五月十六日
+ .NET AOT 下的 F# 命令行参数解析库选择
</a>
</div>
- <span class="post-date">May 16, 2024</span>
+ <span class="post-date">Jun 6, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/13/%E7%BB%99%E5%B0%B8%E4%BD%93%E4%B8%8A-ECMO-%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3/">
+ <a href="/2024/05/20/Rescript-genType-import-%E9%97%AE%E9%A2%98/">
- 给尸体上 ECMO 并维持心跳
+ Rescript @genType import 问题
</a>
</div>
- <span class="post-date">May 13, 2024</span>
+ <span class="post-date">May 20, 2024</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/05/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%83%E6%97%A5/">
+ <a href="/2024/05/16/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E5%8D%81%E5%85%AD%E6%97%A5/">
- 二〇二四年五月七日
+ 二〇二四年五月十六日
</a>
</div>
- <span class="post-date">May 7, 2024</span>
+ <span class="post-date">May 16, 2024</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/04/08/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%9B%9B%E6%9C%88%E5%85%AB%E6%97%A5/">
+ <a href="/2024/05/13/%E7%BB%99%E5%B0%B8%E4%BD%93%E4%B8%8A-ECMO-%E5%B9%B6%E7%BB%B4%E6%8C%81%E5%BF%83%E8%B7%B3/">
- 二〇二四年四月八日
+ 给尸体上 ECMO 并维持心跳
</a>
</div>
- <span class="post-date">Apr 8, 2024</span>
+ <span class="post-date">May 13, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/04/03/shadow-cljs-proxy/">
+ <a href="/2024/05/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%83%E6%97%A5/">
- shadow-cljs 怎么设置代理
+ 二〇二四年五月七日
</a>
</div>
- <span class="post-date">Apr 3, 2024</span>
+ <span class="post-date">May 7, 2024</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="page-number current">2</span><a class="page-number" href="/archives/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="page-number current">2</span><a class="page-number" href="/archives/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/3/index.html b/archives/page/3/index.html
index fe1960e1..5a5d8ee7 100644
--- a/archives/page/3/index.html
+++ b/archives/page/3/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/04/08/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%9B%9B%E6%9C%88%E5%85%AB%E6%97%A5/">
- 二〇二四年三月二十二日
+ 二〇二四年四月八日
</a>
</div>
- <span class="post-date">Mar 22, 2024</span>
+ <span class="post-date">Apr 8, 2024</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/03/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/04/03/shadow-cljs-proxy/">
- 二〇二四年三月十二日
+ shadow-cljs 怎么设置代理
</a>
</div>
- <span class="post-date">Mar 12, 2024</span>
+ <span class="post-date">Apr 3, 2024</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/02/26/OCaml-News-2024-3/">
+ <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
- OCaml News 2024-3
+ 二〇二四年三月二十二日
</a>
</div>
- <span class="post-date">Feb 26, 2024</span>
+ <span class="post-date">Mar 22, 2024</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/02/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%83%E6%97%A5/">
+ <a href="/2024/03/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 二〇二四年二月七日
+ 二〇二四年三月十二日
</a>
</div>
- <span class="post-date">Feb 7, 2024</span>
+ <span class="post-date">Mar 12, 2024</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/25/%E6%80%A5%E8%AF%8A%E4%B8%8E%E7%81%BE%E9%9A%BE%E5%8C%BB%E5%AD%A6-%E7%83%A7%E4%BC%A4/">
+ <a href="/2024/02/26/OCaml-News-2024-3/">
- 急诊与灾难医学--烧伤
+ OCaml News 2024-3
</a>
</div>
- <span class="post-date">Jan 25, 2024</span>
+ <span class="post-date">Feb 26, 2024</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/G-Machine/">
+ <a href="/2024/02/07/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%83%E6%97%A5/">
- G-Machine
+ 二〇二四年二月七日
</a>
</div>
- <span class="post-date">Jan 23, 2024</span>
+ <span class="post-date">Feb 7, 2024</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
+ <a href="/2024/01/25/%E6%80%A5%E8%AF%8A%E4%B8%8E%E7%81%BE%E9%9A%BE%E5%8C%BB%E5%AD%A6-%E7%83%A7%E4%BC%A4/">
- 慢性肺源性心脏病
+ 急诊与灾难医学--烧伤
</a>
</div>
- <span class="post-date">Jan 23, 2024</span>
+ <span class="post-date">Jan 25, 2024</span>
</div>
@@ -270,9 +270,9 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/">
+ <a href="/2024/01/23/G-Machine/">
- 二〇二四年一月二十三日
+ G-Machine
</a>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/22/Rescript-React-Native/">
+ <a href="/2024/01/23/%E6%85%A2%E6%80%A7%E8%82%BA%E6%BA%90%E6%80%A7%E5%BF%83%E8%84%8F%E7%97%85/">
- Rescript and React Native
+ 慢性肺源性心脏病
</a>
</div>
- <span class="post-date">Jan 22, 2024</span>
+ <span class="post-date">Jan 23, 2024</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/18/OCaml-News-2024-2/">
+ <a href="/2024/01/23/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%89%E6%97%A5/">
- OCaml News 2024-2
+ 二〇二四年一月二十三日
</a>
</div>
- <span class="post-date">Jan 18, 2024</span>
+ <span class="post-date">Jan 23, 2024</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><a class="page-number" href="/archives/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/archives/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><a class="page-number" href="/archives/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/archives/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/4/index.html b/archives/page/4/index.html
index 5f9eed35..43466df4 100644
--- a/archives/page/4/index.html
+++ b/archives/page/4/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2024/01/08/OCaml-News-2024-1/">
+ <a href="/2024/01/22/Rescript-React-Native/">
- OCaml News 2024-1
+ Rescript and React Native
</a>
</div>
- <span class="post-date">Jan 8, 2024</span>
+ <span class="post-date">Jan 22, 2024</span>
</div>
@@ -159,19 +159,17 @@
- <div class="year-title">2023</div>
-
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
+ <a href="/2024/01/18/OCaml-News-2024-2/">
- 二〇二三年十二月二日
+ OCaml News 2024-2
</a>
</div>
- <span class="post-date">Dec 2, 2023</span>
+ <span class="post-date">Jan 18, 2024</span>
</div>
@@ -182,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/12/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2024/01/08/OCaml-News-2024-1/">
- 二〇二三年十二月一日
+ OCaml News 2024-1
</a>
</div>
- <span class="post-date">Dec 1, 2023</span>
+ <span class="post-date">Jan 8, 2024</span>
</div>
@@ -197,17 +195,19 @@
+ <div class="year-title">2023</div>
+
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/11/29/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B9%9D%E6%97%A5/">
+ <a href="/2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
- 二〇二三年十一月二十九日
+ 二〇二三年十二月二日
</a>
</div>
- <span class="post-date">Nov 29, 2023</span>
+ <span class="post-date">Dec 2, 2023</span>
</div>
@@ -218,14 +218,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/11/21/Adolescent-Onset-of-Acute-Heart-Failure/">
+ <a href="/2023/12/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/">
- Adolescent Onset of Acute Heart Failure
+ 二〇二三年十二月一日
</a>
</div>
- <span class="post-date">Nov 21, 2023</span>
+ <span class="post-date">Dec 1, 2023</span>
</div>
@@ -236,14 +236,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/11/16/Fever-of-Unknown-Origin/">
+ <a href="/2023/11/29/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B9%9D%E6%97%A5/">
- Fever of Unknown Origin
+ 二〇二三年十一月二十九日
</a>
</div>
- <span class="post-date">Nov 16, 2023</span>
+ <span class="post-date">Nov 29, 2023</span>
</div>
@@ -254,14 +254,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/11/06/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%85%AD%E6%97%A5/">
+ <a href="/2023/11/21/Adolescent-Onset-of-Acute-Heart-Failure/">
- 二零二三年十一月六日
+ Adolescent Onset of Acute Heart Failure
</a>
</div>
- <span class="post-date">Nov 6, 2023</span>
+ <span class="post-date">Nov 21, 2023</span>
</div>
@@ -272,14 +272,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/25/%E5%84%BF%E7%AB%A5%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92Omicron%E6%A0%AA%E5%92%8C%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B7%B7%E5%90%88%E6%84%9F%E6%9F%93%E9%87%8D%E7%97%87%E8%82%BA%E7%82%8E1%E4%BE%8B/">
+ <a href="/2023/11/16/Fever-of-Unknown-Origin/">
- 儿童新型冠状病毒Omicron株和肺炎支原体混合感染重症肺炎1例
+ Fever of Unknown Origin
</a>
</div>
- <span class="post-date">Oct 25, 2023</span>
+ <span class="post-date">Nov 16, 2023</span>
</div>
@@ -290,14 +290,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
+ <a href="/2023/11/06/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%85%AD%E6%97%A5/">
- Radiographic Absence of the Left Humeral Head
+ 二零二三年十一月六日
</a>
</div>
- <span class="post-date">Oct 25, 2023</span>
+ <span class="post-date">Nov 6, 2023</span>
</div>
@@ -308,9 +308,9 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/25/%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/">
+ <a href="/2023/10/25/%E5%84%BF%E7%AB%A5%E6%96%B0%E5%9E%8B%E5%86%A0%E7%8A%B6%E7%97%85%E6%AF%92Omicron%E6%A0%AA%E5%92%8C%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B7%B7%E5%90%88%E6%84%9F%E6%9F%93%E9%87%8D%E7%97%87%E8%82%BA%E7%82%8E1%E4%BE%8B/">
- 肺炎支原体注意事项
+ 儿童新型冠状病毒Omicron株和肺炎支原体混合感染重症肺炎1例
</a>
</div>
@@ -324,7 +324,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/archives/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/archives/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/5/index.html b/archives/page/5/index.html
index a7c821b1..1075b8d7 100644
--- a/archives/page/5/index.html
+++ b/archives/page/5/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/22/%E5%86%AC%E5%AD%A3%E5%92%B3%E5%97%BD%E8%BE%A8%E5%88%AB%E6%8C%87%E5%8D%97/">
+ <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
- 冬季咳嗽辨别指南
+ Radiographic Absence of the Left Humeral Head
</a>
</div>
- <span class="post-date">Oct 22, 2023</span>
+ <span class="post-date">Oct 25, 2023</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/">
+ <a href="/2023/10/25/%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/">
- OCaml Core.Int.pow 的实现
+ 肺炎支原体注意事项
</a>
</div>
- <span class="post-date">Oct 21, 2023</span>
+ <span class="post-date">Oct 25, 2023</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/13/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95/">
+ <a href="/2023/10/22/%E5%86%AC%E5%AD%A3%E5%92%B3%E5%97%BD%E8%BE%A8%E5%88%AB%E6%8C%87%E5%8D%97/">
- 肝功能检查化验单阅读指南
+ 冬季咳嗽辨别指南
</a>
</div>
- <span class="post-date">Oct 13, 2023</span>
+ <span class="post-date">Oct 22, 2023</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/12/%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E7%BB%93%E6%9E%9C%E9%98%85%E8%AF%BB%E6%8C%87%E5%8D%97/">
+ <a href="/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/">
- 血常规化验结果阅读指南
+ OCaml Core.Int.pow 的实现
</a>
</div>
- <span class="post-date">Oct 12, 2023</span>
+ <span class="post-date">Oct 21, 2023</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/12/%E8%BF%87%E5%BA%A6%E7%96%B2%E5%8A%B3%E7%9A%84%E5%85%AD%E7%A7%8D%E8%A1%A8%E7%8E%B0/">
+ <a href="/2023/10/13/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95/">
- 过度疲劳的六种表现
+ 肝功能检查化验单阅读指南
</a>
</div>
- <span class="post-date">Oct 12, 2023</span>
+ <span class="post-date">Oct 13, 2023</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/10/05/v8%E4%B8%AD%E7%9A%84Number-toString/">
+ <a href="/2023/10/12/%E8%A1%80%E5%B8%B8%E8%A7%84%E5%8C%96%E9%AA%8C%E7%BB%93%E6%9E%9C%E9%98%85%E8%AF%BB%E6%8C%87%E5%8D%97/">
- v8中的Number.toString()
+ 血常规化验结果阅读指南
</a>
</div>
- <span class="post-date">Oct 5, 2023</span>
+ <span class="post-date">Oct 12, 2023</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
+ <a href="/2023/10/12/%E8%BF%87%E5%BA%A6%E7%96%B2%E5%8A%B3%E7%9A%84%E5%85%AD%E7%A7%8D%E8%A1%A8%E7%8E%B0/">
- A Brief History of Just-In-Time
+ 过度疲劳的六种表现
</a>
</div>
- <span class="post-date">Sep 28, 2023</span>
+ <span class="post-date">Oct 12, 2023</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/09/13/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%B8%89%E6%97%A5/">
+ <a href="/2023/10/05/v8%E4%B8%AD%E7%9A%84Number-toString/">
- 二零二三年九月十三日
+ v8中的Number.toString()
</a>
</div>
- <span class="post-date">Sep 13, 2023</span>
+ <span class="post-date">Oct 5, 2023</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/08/27/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
+ <a href="/2023/09/28/A-Brief-History-of-Just-In-Time/">
- 二零二三年八月二十七日
+ A Brief History of Just-In-Time
</a>
</div>
- <span class="post-date">Aug 27, 2023</span>
+ <span class="post-date">Sep 28, 2023</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
+ <a href="/2023/09/13/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%B8%89%E6%97%A5/">
- 二零二三年八月二十一日
+ 二零二三年九月十三日
</a>
</div>
- <span class="post-date">Aug 21, 2023</span>
+ <span class="post-date">Sep 13, 2023</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/4/">4</a><span class="page-number current">5</span><a class="page-number" href="/archives/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/4/">4</a><span class="page-number current">5</span><a class="page-number" href="/archives/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/6/index.html b/archives/page/6/index.html
index e34488bb..e697082c 100644
--- a/archives/page/6/index.html
+++ b/archives/page/6/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/08/15/tick-thread%E5%9C%A8Multicore-OCaml%E4%B8%AD%E7%9A%84%E4%BD%9C%E7%94%A8/">
+ <a href="/2023/08/27/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
- tick thread在Multicore OCaml中的作用
+ 二零二三年八月二十七日
</a>
</div>
- <span class="post-date">Aug 15, 2023</span>
+ <span class="post-date">Aug 27, 2023</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/08/15/poll-error-attribute-in-OCaml/">
+ <a href="/2023/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
- 使用 [@poll error] 实现线程安全的数据结构
+ 二零二三年八月二十一日
</a>
</div>
- <span class="post-date">Aug 15, 2023</span>
+ <span class="post-date">Aug 21, 2023</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/08/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2023/08/15/tick-thread%E5%9C%A8Multicore-OCaml%E4%B8%AD%E7%9A%84%E4%BD%9C%E7%94%A8/">
- 二〇二三年八月一日
+ tick thread在Multicore OCaml中的作用
</a>
</div>
- <span class="post-date">Aug 1, 2023</span>
+ <span class="post-date">Aug 15, 2023</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/07/30/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B8%83%E6%9C%88%E4%B8%89%E5%8D%81%E6%97%A5/">
+ <a href="/2023/08/15/poll-error-attribute-in-OCaml/">
- 二零二三年七月三十日
+ 使用 [@poll error] 实现线程安全的数据结构
</a>
</div>
- <span class="post-date">Jul 30, 2023</span>
+ <span class="post-date">Aug 15, 2023</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/07/21/WiscKey-Separating-Keys-from-Values-in-SSD-conscious-Storage/">
+ <a href="/2023/08/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
- WiscKey: Separating Keys from Values in SSD-conscious Storage
+ 二〇二三年八月一日
</a>
</div>
- <span class="post-date">Jul 21, 2023</span>
+ <span class="post-date">Aug 1, 2023</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/29/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B9%9D%E6%97%A5/">
+ <a href="/2023/07/30/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B8%83%E6%9C%88%E4%B8%89%E5%8D%81%E6%97%A5/">
- 二〇二三年六月二十九日
+ 二零二三年七月三十日
</a>
</div>
- <span class="post-date">Jun 29, 2023</span>
+ <span class="post-date">Jul 30, 2023</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
+ <a href="/2023/07/21/WiscKey-Separating-Keys-from-Values-in-SSD-conscious-Storage/">
- 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
+ WiscKey: Separating Keys from Values in SSD-conscious Storage
</a>
</div>
- <span class="post-date">Jun 28, 2023</span>
+ <span class="post-date">Jul 21, 2023</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/28/caml-release-runtime-system%E5%AF%BC%E8%87%B4%E7%9A%84%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98/">
+ <a href="/2023/06/29/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B9%9D%E6%97%A5/">
- caml_release_runtime_system导致的死锁问题
+ 二〇二三年六月二十九日
</a>
</div>
- <span class="post-date">Jun 28, 2023</span>
+ <span class="post-date">Jun 29, 2023</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/22/%E7%81%AF%E7%AC%BC%E8%8D%89/">
+ <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
- 灯笼草
+ 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
</a>
</div>
- <span class="post-date">Jun 22, 2023</span>
+ <span class="post-date">Jun 28, 2023</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/17/%E5%8F%91%E7%83%AD%E5%8F%8A%E8%B6%85%E9%AB%98%E7%83%AD%E5%8D%B1%E8%B1%A1/">
+ <a href="/2023/06/28/caml-release-runtime-system%E5%AF%BC%E8%87%B4%E7%9A%84%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98/">
- 发热及超高热危象
+ caml_release_runtime_system导致的死锁问题
</a>
</div>
- <span class="post-date">Jun 17, 2023</span>
+ <span class="post-date">Jun 28, 2023</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/archives/page/7/">7</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/archives/page/7/">7</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/7/index.html b/archives/page/7/index.html
index 4a6d9d85..92505250 100644
--- a/archives/page/7/index.html
+++ b/archives/page/7/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/06/10/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E5%8D%81%E6%97%A5/">
+ <a href="/2023/06/22/%E7%81%AF%E7%AC%BC%E8%8D%89/">
- 二零二三年六月十日
+ 灯笼草
</a>
</div>
- <span class="post-date">Jun 10, 2023</span>
+ <span class="post-date">Jun 22, 2023</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
+ <a href="/2023/06/17/%E5%8F%91%E7%83%AD%E5%8F%8A%E8%B6%85%E9%AB%98%E7%83%AD%E5%8D%B1%E8%B1%A1/">
- Rust 闭包 lifetime may not live long enough 问题
+ 发热及超高热危象
</a>
</div>
- <span class="post-date">May 24, 2023</span>
+ <span class="post-date">Jun 17, 2023</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/">
+ <a href="/2023/06/10/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E5%8D%81%E6%97%A5/">
- C++ 20 实现 string split
+ 二零二三年六月十日
</a>
</div>
- <span class="post-date">May 12, 2023</span>
+ <span class="post-date">Jun 10, 2023</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/11/C-vector-%E7%9A%84-push-back-%E5%92%8C-emplace-back/">
+ <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
- C++ vector 的 push_back 和 emplace_back
+ Rust 闭包 lifetime may not live long enough 问题
</a>
</div>
- <span class="post-date">May 11, 2023</span>
+ <span class="post-date">May 24, 2023</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/04/C-%E7%9A%84-Trait/">
+ <a href="/2023/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/">
- C++ 的 Trait
+ C++ 20 实现 string split
</a>
</div>
- <span class="post-date">May 4, 2023</span>
+ <span class="post-date">May 12, 2023</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/03/Rust-NewType-%E6%A8%A1%E5%BC%8F/">
+ <a href="/2023/05/11/C-vector-%E7%9A%84-push-back-%E5%92%8C-emplace-back/">
- Rust NewType 模式
+ C++ vector 的 push_back 和 emplace_back
</a>
</div>
- <span class="post-date">May 3, 2023</span>
+ <span class="post-date">May 11, 2023</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/02/Rust-Partial-%E8%AF%AD%E4%B9%89/">
+ <a href="/2023/05/04/C-%E7%9A%84-Trait/">
- Rust Partial 语义
+ C++ 的 Trait
</a>
</div>
- <span class="post-date">May 2, 2023</span>
+ <span class="post-date">May 4, 2023</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/">
+ <a href="/2023/05/03/Rust-NewType-%E6%A8%A1%E5%BC%8F/">
- Rust 虚表布局规则介绍
+ Rust NewType 模式
</a>
</div>
- <span class="post-date">May 1, 2023</span>
+ <span class="post-date">May 3, 2023</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/">
+ <a href="/2023/05/02/Rust-Partial-%E8%AF%AD%E4%B9%89/">
- TypeScript With Rust Errors, No Try Catch, Heresy
+ Rust Partial 语义
</a>
</div>
- <span class="post-date">Apr 30, 2023</span>
+ <span class="post-date">May 2, 2023</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/04/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
+ <a href="/2023/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/">
- 二零二三年四月二十五日
+ Rust 虚表布局规则介绍
</a>
</div>
- <span class="post-date">Apr 25, 2023</span>
+ <span class="post-date">May 1, 2023</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/archives/page/8/">8</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/archives/page/8/">8</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/8/index.html b/archives/page/8/index.html
index fd93b346..60ee22f5 100644
--- a/archives/page/8/index.html
+++ b/archives/page/8/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/04/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/">
- 二零二三年四月二十二日
+ TypeScript With Rust Errors, No Try Catch, Heresy
</a>
</div>
- <span class="post-date">Apr 22, 2023</span>
+ <span class="post-date">Apr 30, 2023</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/14/%E8%9E%BA%E5%86%85%E9%85%AF%E7%89%87/">
+ <a href="/2023/04/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
- 螺内酯片
+ 二零二三年四月二十五日
</a>
</div>
- <span class="post-date">Mar 14, 2023</span>
+ <span class="post-date">Apr 25, 2023</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/14/%E5%91%8B%E5%A1%9E%E7%B1%B3/">
+ <a href="/2023/04/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%9B%9B%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 呋塞米
+ 二零二三年四月二十二日
</a>
</div>
- <span class="post-date">Mar 14, 2023</span>
+ <span class="post-date">Apr 22, 2023</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/13/%E6%9B%BF%E7%B1%B3%E6%B2%99%E5%9D%A6/">
+ <a href="/2023/03/14/%E8%9E%BA%E5%86%85%E9%85%AF%E7%89%87/">
- 替米沙坦
+ 螺内酯片
</a>
</div>
- <span class="post-date">Mar 13, 2023</span>
+ <span class="post-date">Mar 14, 2023</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
+ <a href="/2023/03/14/%E5%91%8B%E5%A1%9E%E7%B1%B3/">
- 奥司他韦
+ 呋塞米
</a>
</div>
- <span class="post-date">Mar 5, 2023</span>
+ <span class="post-date">Mar 14, 2023</span>
</div>
@@ -234,14 +234,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
+ <a href="/2023/03/13/%E6%9B%BF%E7%B1%B3%E6%B2%99%E5%9D%A6/">
- 金匮要略
+ 替米沙坦
</a>
</div>
- <span class="post-date">Mar 4, 2023</span>
+ <span class="post-date">Mar 13, 2023</span>
</div>
@@ -252,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/01/%E6%B0%94%E8%83%B8/">
+ <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
- 气胸
+ 奥司他韦
</a>
</div>
- <span class="post-date">Mar 1, 2023</span>
+ <span class="post-date">Mar 5, 2023</span>
</div>
@@ -270,14 +270,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/03/01/%E7%BA%AF%E7%89%9B%E5%A5%B6%E5%8F%AF%E4%BB%A5%E5%8A%A0%E7%82%B9%E5%95%A5/">
+ <a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
- 纯牛奶可以加点啥
+ 金匮要略
</a>
</div>
- <span class="post-date">Mar 1, 2023</span>
+ <span class="post-date">Mar 4, 2023</span>
</div>
@@ -288,14 +288,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/26/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%85%AD%E6%97%A5/">
+ <a href="/2023/03/01/%E6%B0%94%E8%83%B8/">
- 二零二三年二月二十六日
+ 气胸
</a>
</div>
- <span class="post-date">Feb 26, 2023</span>
+ <span class="post-date">Mar 1, 2023</span>
</div>
@@ -306,14 +306,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
+ <a href="/2023/03/01/%E7%BA%AF%E7%89%9B%E5%A5%B6%E5%8F%AF%E4%BB%A5%E5%8A%A0%E7%82%B9%E5%95%A5/">
- 二零二三年二月二十五日
+ 纯牛奶可以加点啥
</a>
</div>
- <span class="post-date">Feb 25, 2023</span>
+ <span class="post-date">Mar 1, 2023</span>
</div>
@@ -322,7 +322,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/7/">7</a><span class="page-number current">8</span><a class="page-number" href="/archives/page/9/">9</a><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/7/">7</a><span class="page-number current">8</span><a class="page-number" href="/archives/page/9/">9</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/archives/page/9/index.html b/archives/page/9/index.html
index 46973296..8b839f49 100644
--- a/archives/page/9/index.html
+++ b/archives/page/9/index.html
@@ -144,14 +144,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/24/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/">
+ <a href="/2023/02/26/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%85%AD%E6%97%A5/">
- 二零二三年二月二十四日
+ 二零二三年二月二十六日
</a>
</div>
- <span class="post-date">Feb 24, 2023</span>
+ <span class="post-date">Feb 26, 2023</span>
</div>
@@ -162,14 +162,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2023/02/25/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%94%E6%97%A5/">
- 二零二三年二月二十二日
+ 二零二三年二月二十五日
</a>
</div>
- <span class="post-date">Feb 22, 2023</span>
+ <span class="post-date">Feb 25, 2023</span>
</div>
@@ -180,14 +180,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/02/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
+ <a href="/2023/02/24/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/">
- 二零二三年二月二日
+ 二零二三年二月二十四日
</a>
</div>
- <span class="post-date">Feb 2, 2023</span>
+ <span class="post-date">Feb 24, 2023</span>
</div>
@@ -198,14 +198,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/02/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2023/02/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
- 二零二三年二月一日
+ 二零二三年二月二十二日
</a>
</div>
- <span class="post-date">Feb 1, 2023</span>
+ <span class="post-date">Feb 22, 2023</span>
</div>
@@ -216,14 +216,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2023/01/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
+ <a href="/2023/02/02/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
- 二零二三年一月二十一日
+ 二零二三年二月二日
</a>
</div>
- <span class="post-date">Jan 21, 2023</span>
+ <span class="post-date">Feb 2, 2023</span>
</div>
@@ -231,19 +231,17 @@
- <div class="year-title">2022</div>
-
<div class="post-list-item">
<div class="post-title">
- <a href="/2022/12/31/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/">
+ <a href="/2023/02/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/">
- 二零二二年十二月三十一日
+ 二零二三年二月一日
</a>
</div>
- <span class="post-date">Dec 31, 2022</span>
+ <span class="post-date">Feb 1, 2023</span>
</div>
@@ -254,14 +252,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2022/11/03/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E6%9C%88%E4%B8%89%E6%97%A5/">
+ <a href="/2023/01/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
- 二零二二年十一月月三日
+ 二零二三年一月二十一日
</a>
</div>
- <span class="post-date">Nov 3, 2022</span>
+ <span class="post-date">Jan 21, 2023</span>
</div>
@@ -269,17 +267,19 @@
+ <div class="year-title">2022</div>
+
<div class="post-list-item">
<div class="post-title">
- <a href="/2022/10/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E6%9C%88%E4%B8%80%E6%97%A5/">
+ <a href="/2022/12/31/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/">
- 二零二二年十月一日
+ 二零二二年十二月三十一日
</a>
</div>
- <span class="post-date">Oct 1, 2022</span>
+ <span class="post-date">Dec 31, 2022</span>
</div>
@@ -290,14 +290,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2022/09/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+ <a href="/2022/11/03/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E6%9C%88%E4%B8%89%E6%97%A5/">
- 二零二二年九月二十二日
+ 二零二二年十一月月三日
</a>
</div>
- <span class="post-date">Sep 22, 2022</span>
+ <span class="post-date">Nov 3, 2022</span>
</div>
@@ -308,14 +308,14 @@
<div class="post-list-item">
<div class="post-title">
- <a href="/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/">
+ <a href="/2022/10/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E6%9C%88%E4%B8%80%E6%97%A5/">
- 二零二二年八月二十一日
+ 二零二二年十月一日
</a>
</div>
- <span class="post-date">Aug 21, 2022</span>
+ <span class="post-date">Oct 1, 2022</span>
</div>
@@ -324,7 +324,7 @@
<div class=paginator>
<div class="h-line-primary"></div>
<nav class="pagination">
- <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><span class="page-number current">9</span><a class="page-number" href="/archives/page/10/">10</a>
+ <a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><span class="page-number current">9</span><a class="page-number" href="/archives/page/10/">10</a><a class="page-number" href="/archives/page/11/">11</a>
</nav>
</div>
diff --git a/page/11/index.html b/page/11/index.html
new file mode 100644
index 00000000..3215b512
--- /dev/null
+++ b/page/11/index.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <div class="profile">
+ <div class="profile-image">
+
+ <img src="/profile_cover.jpg" alt="featured_image">
+
+ </div>
+ <div class="post-content profile-content">
+ <div class="profile-title">
+ 暮秋小屋
+ </div>
+ <div class="profile-body">
+ 思念、灵感、文档的寄存处
+ </div>
+
+ <div class="profile-link">
+ <a href="/archives/">归档</a>
+ </div>
+
+ <div class="profile-link">
+ <a href="/tags/Technique/">计算机科学</a>
+ </div>
+
+ <div class="profile-link">
+ <a href="/tags/Medicine/">医学</a>
+ </div>
+
+ <div class="profile-link">
+ <a href="/tags/Life/">生活</a>
+ </div>
+
+ <div class="profile-link">
+ <a href="/categories/gallery/">日记本</a>
+ </div>
+
+ <div class="profile-link">
+ <a href="/about">关于我</a>
+ </div>
+
+ </div>
+
+</div>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/search.xml b/search.xml
index 37264e9c..1a6ff8c8 100644
--- a/search.xml
+++ b/search.xml
@@ -48,6 +48,107 @@
</tags>
</entry>
<entry>
+ <title>Advanced C binding using ocaml-ctypes and dune</title>
+ <url>/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/</url>
+ <content><![CDATA[<p>I was working on a OCaml binding for <a href="https://github.com/Haivision/srt">libsrt</a> last summer, to add support for SRT real-time input and output to <a href="https://github.com/savonet/liquidsoap">liquidsoap</a>, and came across the need to access the <code>[sys/socket.h](https://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html)</code> C API.</p>
+<p>I had already decided to use the very elegant <code>[ocaml-ctypes](https://github.com/ocamllabs/ocaml-ctypes)</code> module for the SRT binding so I went with it and created a <code>[ocaml-sys-socket](https://github.com/toots/ocaml-sys-socket)</code> module using it as well. It was a very interesting experience that I would like to describe here!</p>
+<h1 id="ocaml-ctypes"><a href="#ocaml-ctypes" class="headerlink" title="ocaml-ctypes"></a>ocaml-ctypes</h1><p>The idea behind OCaml ctypes is to create a binding against a C library without having to write C code, or as least as possible. The most straight-forward way of using it is via <code>[libffi](https://github.com/libffi/libffi)</code> , providing access to dynamically-loaded libraries.</p>
+<p>The second way of using it is by letting the module generate the basic C stubs required to build and link against a shared library. This is the mode that we’re going to use here. In this mode, the programmer has to describe the C headers of the library they intent to bind to using dedicated OCaml modules, operators and types. From that description, ocaml-ctypes is able to generate the required glue for the binding.</p>
+<p>One advantage of using ocaml-ctypes is that the created bindings make as few assumptions as possible about the <a href="https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html">OCaml C interfacing API</a>. This is pretty nice, in particular since the <a href="https://github.com/ocaml/ocaml">OCaml compiler</a> is moving pretty quickly these days (which is awesome!) and also if, perhaps one day, <a href="https://github.com/ocaml-multicore/ocaml-multicore">support for multi-core</a> is added to the compiler, which will undoubtedly change the C interface API quite a bit.</p>
+<h1 id="dune"><a href="#dune" class="headerlink" title="dune"></a>dune</h1><p><code>[dune](https://github.com/ocaml/dune)</code> (formally <code>jbuilder</code> ) is a build system for OCaml projects that has recently raised to much popularity, particularly due to its tight integration with the rest of the OCaml ecosystem, such as <code>[ocamlfind](http://projects.camlcity.org/projects/findlib.html)</code> and <code>[opam](https://opam.ocaml.org/)</code> .</p>
+<p>My personal motto in programming in general is that <em>“Simple things should be simple, but complex things should be possible”</em>. <code>dune</code> certainly does not fit into that category but, rather, makes some complex things extremely easy to setup. It’s the kind of tool that will make your life incredibly easier when what you intent to do fits well within their workflow but might not be easy to bend to some very specific niche use. We will see one such case below.</p>
+<p>At any rate, it’s been an amazing experience getting to learn how to use <code>dune</code> and the resulting code and build system is remarkably short and elegant, yet very powerful.</p>
+<h1 id="socket-h"><a href="#socket-h" class="headerlink" title="socket.h"></a>socket.h</h1><p><code>socket.h</code> is the Unix header that describes the C API to various socket operations, IP version 4 and 6 as well as unix file sockets. There is also a windows API mimicking it, which makes most code using it easily portable to windows.</p>
+<p>Most network-based C libraries refer to <code>socket.h</code> to describe the type of socket that can be used with their API so it’s an important entry point for a lot of network operations and one that would be nice to support as generically as possible in OCaml.</p>
+<p>The catch, though, is that, most likely for historical reasons¹, the <a href="https://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html">POSIX specifications</a> only <em>partially</em> defines some of the required data structures and types, which makes it possible to write C code using them but does not give enough information to write C bindings without having to use the compiler to parse the actual system-specific headers of the running host.</p>
+<p>For instance, here’s how the <code>sockaddr</code> structure is specified:</p>
+<p>The <em>&lt;sys&#x2F;socket.h&gt;</em> header defines the <strong>sockaddr</strong> structure that includes at least the following members:sa_family_t sa_family address family<br>char sa_data[] socket address (variable-length data)</p>
+<p>Likewise, here’s what is specified about the size of the <code>socklen_t</code> data type:</p>
+<p><em>&lt;sys&#x2F;socket.h&gt;</em> makes available a type, <strong>socklen_t</strong>, which is an unsigned opaque integral type of length of at least 32 bits.</p>
+<p>Thus, in order to know the exact offset of <code>sa_family</code> inside the <code>sockaddr</code> structure or the actual size of a <code>socklen_t</code> integer, one has to include the OS-specific header, parse its definitions for that specific OS and, only then, is it possible to compute that offset or data size. Let’s see how it’s done in our binding now!</p>
+<h1 id="Putting-it-together"><a href="#Putting-it-together" class="headerlink" title="Putting it together"></a>Putting it together</h1><p>The C binding requires 4 separate passes:</p>
+<ul>
+<li>The <code>[constants](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/constants)</code> pass, which computes and exports some specific constant and data sizes, computed from the C headers</li>
+<li>The <code>[types](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/types)</code> pass, which, given the system-specific constants and sizes exported in the previous phase, defines the actual C data structure bindings.</li>
+<li>The <code>[stubs](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/stubs)</code> pass, where we define the actual bindings to the C functions that we wish to export in our API.</li>
+<li>Finally, the <a href="https://github.com/toots/ocaml-sys-socket/blob/master/src/sys-socket/sys_socket.mli">last pass</a> does a cleanup of the <code>stubs</code> pass to export a relevant and OCaml- (and <code>ocaml-ctypes</code>) specific public API that is to be used by users of the module.</li>
+</ul>
+<p><code>dune</code> makes each of these steps fairly easy to integrate into the next one, defining compilation elements and binaries to build before moving to the next pass.</p>
+<h2 id="Constants-pass"><a href="#Constants-pass" class="headerlink" title="Constants pass"></a>Constants pass</h2><p>During that pass, we compute and export all required C values defined in the headers. We also add our own constants, which give us the sizes that the POSIX specifications leave up to the OS. Here’s the OCaml code for it:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">let</span> af_inet = <span class="type">S</span>.constant <span class="string">&quot;AF_INET&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_inet6 = <span class="type">S</span>.constant <span class="string">&quot;AF_INET6&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_unix = <span class="type">S</span>.constant <span class="string">&quot;AF_UNIX&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> af_unspec = <span class="type">S</span>.constant <span class="string">&quot;AF_UNSPEC&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sa_data_len = <span class="type">S</span>.constant <span class="string">&quot;SA_DATA_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sa_family_len = <span class="type">S</span>.constant <span class="string">&quot;SA_FAMILY_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_dgram = <span class="type">S</span>.constant <span class="string">&quot;SOCK_DGRAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_stream = <span class="type">S</span>.constant <span class="string">&quot;SOCK_STREAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> sock_seqpacket = <span class="type">S</span>.constant <span class="string">&quot;SOCK_STREAM&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> socklen_t_len = <span class="type">S</span>.constant <span class="string">&quot;SOCKLEN_T_LEN&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_maxserv = <span class="type">S</span>.constant <span class="string">&quot;NI_MAXSERV&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_maxhost = <span class="type">S</span>.constant <span class="string">&quot;NI_MAXHOST&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_numerichost = <span class="type">S</span>.constant <span class="string">&quot;NI_NUMERICHOST&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"> <span class="keyword">let</span> ni_numericserv = <span class="type">S</span>.constant <span class="string">&quot;NI_NUMERICSERV&quot;</span> <span class="type">S</span>.<span class="built_in">int</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>Pretty straightforward! Some of these constants are defined by the POSIX headers and some are custom defined for our needs, for instance <code>SOCKLEN_T_LEN</code> . Here’s how they are extracted, using the <code>dune</code> build configuration for <code>[gen_constants_c](https://github.com/toots/ocaml-sys-socket/blob/master/src/sys-socket/generator/gen_constants_c.ml)</code>:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;sys/un.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#define SA_DATA_LEN (sizeof(((struct sockaddr*)0)-&gt;sa_data))</span></span><br><span class="line"><span class="string">#define SA_FAMILY_LEN (sizeof(((struct sockaddr*)0)-&gt;sa_family))</span></span><br><span class="line"><span class="string">#define SOCKLEN_T_LEN (sizeof(socklen_t))</span></span><br><span class="line"><span class="string">#ifndef NI_MAXHOST</span></span><br><span class="line"><span class="string"> #define NI_MAXHOST 1025</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#ifndef NI_MAXSERV</span></span><br><span class="line"><span class="string"> #define NI_MAXSERV 32</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.<span class="type">Types</span>.write_c format (<span class="keyword">module</span> <span class="type">Sys_socket_constants</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>This OCaml code makes use of <code>ocaml-ctypes</code> to build a binary that exports the OCaml interface defined by <code>Sys_socket_constants.Def</code> . Once compiled, its output looks like this:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">include</span> <span class="type">Ctypes</span></span><br><span class="line"><span class="keyword">let</span> lift x = x</span><br><span class="line"><span class="keyword">open</span> <span class="type">Ctypes_static</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> field : <span class="keyword">type</span> t a. t typ -&gt; <span class="built_in">string</span> -&gt; a typ -&gt; (a, t) field =</span><br><span class="line"> <span class="keyword">fun</span> s fname ftype -&gt; <span class="keyword">match</span> s, fname <span class="keyword">with</span></span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125;, _ -&gt;</span><br><span class="line"> <span class="keyword">let</span> &#123; ftype; foffset; fname &#125; = field ty fname ftype <span class="keyword">in</span></span><br><span class="line"> &#123; ftype; foffset; fname &#125;</span><br><span class="line"> | _ -&gt; failwith (<span class="string">&quot;Unexpected field &quot;</span>^ fname)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> seal : <span class="keyword">type</span> a. a typ -&gt; <span class="built_in">unit</span> = <span class="keyword">function</span></span><br><span class="line"> | <span class="type">Struct</span> &#123; tag; spec = <span class="type">Complete</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> tag)</span><br><span class="line"> | <span class="type">Union</span> &#123; utag; uspec = <span class="type">Some</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> utag)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125; -&gt; seal ty</span><br><span class="line"> | _ -&gt;</span><br><span class="line"> raise (<span class="type">Unsupported</span> <span class="string">&quot;Sealing a non-structured type&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="symbol">&#x27;a</span> const = <span class="symbol">&#x27;a</span></span><br><span class="line"><span class="keyword">let</span> constant (<span class="keyword">type</span> t) name (t : t typ) : t = <span class="keyword">match</span> t, name <span class="keyword">with</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_NUMERICSERV&quot;</span> -&gt;</span><br><span class="line"> <span class="number">8</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_NUMERICHOST&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_MAXHOST&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1025</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;NI_MAXSERV&quot;</span> -&gt;</span><br><span class="line"> <span class="number">32</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCKLEN_T_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">4</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_STREAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_STREAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SOCK_DGRAM&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SA_FAMILY_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;SA_DATA_LEN&quot;</span> -&gt;</span><br><span class="line"> <span class="number">14</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_UNSPEC&quot;</span> -&gt;</span><br><span class="line"> <span class="number">0</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_UNIX&quot;</span> -&gt;</span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_INET6&quot;</span> -&gt;</span><br><span class="line"> <span class="number">30</span></span><br><span class="line"> | <span class="type">Ctypes_static</span>.<span class="type">Primitive</span> <span class="type">Cstubs_internals</span>.<span class="type">Int</span>, <span class="string">&quot;AF_INET&quot;</span> -&gt;</span><br><span class="line"> <span class="number">2</span></span><br><span class="line"> | _, s -&gt; failwith (<span class="string">&quot;unmatched constant: &quot;</span>^ s)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> enum (<span class="keyword">type</span> a) name ?typedef ?unexpected (alist : (a * <span class="built_in">int64</span>) <span class="built_in">list</span>) =</span><br><span class="line"> <span class="keyword">match</span> name <span class="keyword">with</span></span><br><span class="line"> | s -&gt;</span><br><span class="line"> failwith (<span class="string">&quot;unmatched enum: &quot;</span>^ s)</span><br></pre></td></tr></table></figure>
+
+<p>The files used to describe how to build this binary using <code>dune</code> are located in a separate <code>[generator](https://github.com/toots/ocaml-sys-socket/tree/master/src/sys-socket/generator)</code> directory. Here’s the entry to build this one:</p>
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">(executable</span><br><span class="line"> (name gen_constants_c)</span><br><span class="line"> (modules gen_constants_c)</span><br><span class="line"> (libraries sys-socket.constants ctypes.stubs))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_constants.c)</span><br><span class="line"> (deps (:gen ./gen_constants_c.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_constants_c)</span><br><span class="line"> (deps (:c_code ./gen_constants.c))</span><br><span class="line"> (action (run %&#123;ocaml-config:c_compiler&#125; -I %&#123;lib:ctypes:&#125; -I %&#123;ocaml-config:standard_library&#125; -o %&#123;targets&#125; %&#123;c_code&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>This executable is compiled during the next phase. Let’s move into it now!</p>
+<h2 id="Types-pass"><a href="#Types-pass" class="headerlink" title="Types pass"></a>Types pass</h2><p>During that phase, we use the constants exported during the previous phase to describe the various C structures and types. This is by far the most complex part of the code, making use of first-class modules and several OCaml tricks.</p>
+<p>First, let’s look at how we tell <code>dune</code> that we need to generate the <code>.ml</code> file exporting our required constants from the previous pass:</p>
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_constants.ml)</span><br><span class="line"> (deps (:exec ../generator/exec.sh)</span><br><span class="line"> (:gen ../generator/gen_constants_c))</span><br><span class="line"> (action (with-stdout-to %&#123;targets&#125;</span><br><span class="line"> (system &quot;%&#123;exec&#125; %&#123;ocaml-config:system&#125; %&#123;gen&#125;&quot;))))</span><br></pre></td></tr></table></figure>
+
+<p>With only this information, if the code refers to a <code>Sys_socket_generated_constants</code> module, <code>dune</code> will know that this module needs to be generated and how to do it. We will explain later the use of the <code>exec.sh</code> wrapper here.</p>
+<p>Now that we can make use of the exported constants in our OCaml code, let’s see how we define the <code>Socklen</code> module, exporting abstract types and interface to use <code>socklen_t</code> integers:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="type">Constants</span> = <span class="type">Sys_socket_constants</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_constants</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="keyword">type</span> <span class="type">Socklen</span> = <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> socklen</span><br><span class="line"> <span class="keyword">val</span> socklen_t : socklen <span class="type">S</span>.typ</span><br><span class="line"> <span class="keyword">val</span> int_of_socklen : socklen -&gt; <span class="built_in">int</span></span><br><span class="line"> <span class="keyword">val</span> socklen_of_int : <span class="built_in">int</span> -&gt; socklen</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> socklen : (<span class="keyword">module</span> <span class="type">Socklen</span>) =</span><br><span class="line"> <span class="keyword">match</span> <span class="type">Constants</span>.socklen_t_len <span class="keyword">with</span></span><br><span class="line"> | <span class="number">4</span> -&gt; (<span class="keyword">module</span> <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> socklen = <span class="type">Unsigned</span>.uint32</span><br><span class="line"> <span class="keyword">let</span> socklen_t = <span class="type">S</span>.uint32_t</span><br><span class="line"> <span class="keyword">let</span> int_of_socklen = <span class="type">Unsigned</span>.<span class="type">UInt32</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> socklen_of_int = <span class="type">Unsigned</span>.<span class="type">UInt32</span>.of_int</span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line"> | <span class="number">8</span> -&gt; (<span class="keyword">module</span> <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> socklen = <span class="type">Unsigned</span>.uint64</span><br><span class="line"> <span class="keyword">let</span> socklen_t = <span class="type">S</span>.uint64_t</span><br><span class="line"> <span class="keyword">let</span> int_of_socklen = <span class="type">Unsigned</span>.<span class="type">UInt64</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> socklen_of_int = <span class="type">Unsigned</span>.<span class="type">UInt64</span>.of_int</span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line"> | _ -&gt; <span class="keyword">assert</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Socklen</span> = (<span class="keyword">val</span> socklen : <span class="type">Socklen</span>)</span><br></pre></td></tr></table></figure>
+
+<p>As you can see, we make use of first-order modules and the size of the <code>socklen_t</code> integer to define the right API for the compiling host. Now let’s see how we define the <code>sockaddr</code> interface:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">module</span> <span class="keyword">type</span> <span class="type">SaFamily</span> = <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> sa_family</span><br><span class="line"> <span class="keyword">val</span> int_of_sa_family : sa_family -&gt; <span class="built_in">int</span></span><br><span class="line"> <span class="keyword">val</span> sa_family_of_int : <span class="built_in">int</span> -&gt; sa_family</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">module</span> <span class="type">T</span> : <span class="keyword">functor</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) -&gt; <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">val</span> t : sa_family <span class="type">S</span>.typ</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> saFamily : (<span class="keyword">module</span> <span class="type">SaFamily</span>) =</span><br><span class="line"> <span class="keyword">match</span> <span class="type">Constants</span>.sa_family_len <span class="keyword">with</span></span><br><span class="line"> | <span class="number">1</span> -&gt; (<span class="keyword">module</span> <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> sa_family = <span class="type">Unsigned</span>.uint8</span><br><span class="line"> <span class="keyword">let</span> int_of_sa_family = <span class="type">Unsigned</span>.<span class="type">UInt8</span>.to_int</span><br><span class="line"> <span class="keyword">let</span> sa_family_of_int = <span class="type">Unsigned</span>.<span class="type">UInt8</span>.of_int </span><br><span class="line"> <span class="keyword">module</span> <span class="type">T</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">let</span> t = <span class="type">S</span>.uint8_t</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span>)</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">SaFamily</span> = (<span class="keyword">val</span> saFamily : <span class="type">SaFamily</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">S</span> : <span class="type">Cstubs</span>.<span class="type">Types</span>.<span class="type">TYPE</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Constants</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Socklen</span>(<span class="type">S</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">include</span> <span class="type">SaFamily</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">SaFamilyT</span> = <span class="type">SaFamily</span>.<span class="type">T</span>(<span class="type">S</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> sa_family_t = <span class="type">S</span>.typedef <span class="type">SaFamilyT</span>.t <span class="string">&quot;sa_family_t&quot;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">Sockaddr</span> = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">type</span> t = <span class="built_in">unit</span></span><br><span class="line"> <span class="keyword">let</span> t = <span class="type">S</span>.structure <span class="string">&quot;sockaddr&quot;</span></span><br><span class="line"> <span class="keyword">let</span> sa_family = <span class="type">S</span>.field t <span class="string">&quot;sa_family&quot;</span> sa_family_t</span><br><span class="line"> <span class="keyword">let</span> sa_data = <span class="type">S</span>.field t <span class="string">&quot;sa_data&quot;</span> (<span class="type">S</span>.<span class="built_in">array</span> sa_data_len <span class="type">S</span>.<span class="built_in">char</span>)</span><br><span class="line"> <span class="keyword">let</span> <span class="literal">()</span> = <span class="type">S</span>.seal t</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> </span><br><span class="line"> ...</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>Here, too, we make use of the size of <code>sa_family</code> as exported previously to define the right structure fields.</p>
+<p>Next step, we need to compile this interface again to export the right offset for the various structures that have been defined. That’s <code>dune</code>’s job again!</p>
+<p>First, the generator code:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;sys/un.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netinet/in.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.<span class="type">Types</span>.write_c format (<span class="keyword">module</span> <span class="type">Sys_socket_types</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>And the build instructions:</p>
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">(executable</span><br><span class="line"> (name gen_types_c)</span><br><span class="line"> (modules gen_types_c)</span><br><span class="line"> (libraries sys-socket.types ctypes.stubs))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_types.c)</span><br><span class="line"> (deps (:gen ./gen_types_c.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets gen_types_c)</span><br><span class="line"> (deps (:c_code ./gen_types.c))</span><br><span class="line"> (action (run %&#123;ocaml-config:c_compiler&#125; -I %&#123;lib:ctypes:&#125; -I %&#123;ocaml-config:standard_library&#125; -o %&#123;targets&#125; %&#123;c_code&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>Once, compiled, the exported <code>.ml</code> looks like this:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">include</span> <span class="type">Ctypes</span></span><br><span class="line"><span class="keyword">let</span> lift x = x</span><br><span class="line"><span class="keyword">open</span> <span class="type">Ctypes_static</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> field : <span class="keyword">type</span> t a. t typ -&gt; <span class="built_in">string</span> -&gt; a typ -&gt; (a, t) field =</span><br><span class="line"> <span class="keyword">fun</span> s fname ftype -&gt; <span class="keyword">match</span> s, fname <span class="keyword">with</span></span><br><span class="line">...</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>&#125; <span class="keyword">as</span> s&#x27;), <span class="string">&quot;sa_data&quot;</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> f = &#123;ftype; fname; foffset = <span class="number">2</span>&#125; <span class="keyword">in</span></span><br><span class="line"> (s&#x27;.fields &lt;- <span class="type">BoxedField</span> f :: s&#x27;.fields; f)</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>&#125; <span class="keyword">as</span> s&#x27;), <span class="string">&quot;sa_family&quot;</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> f = &#123;ftype; fname; foffset = <span class="number">1</span>&#125; <span class="keyword">in</span></span><br><span class="line"> (s&#x27;.fields &lt;- <span class="type">BoxedField</span> f :: s&#x27;.fields; f)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125;, _ -&gt;</span><br><span class="line"> <span class="keyword">let</span> &#123; ftype; foffset; fname &#125; = field ty fname ftype <span class="keyword">in</span></span><br><span class="line"> &#123; ftype; foffset; fname &#125;</span><br><span class="line"> | _ -&gt; failwith (<span class="string">&quot;Unexpected field &quot;</span>^ fname)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">rec</span> seal : <span class="keyword">type</span> a. a typ -&gt; <span class="built_in">unit</span> = <span class="keyword">function</span></span><br><span class="line">...</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr_storage&quot;</span>; spec = <span class="type">Incomplete</span> _ &#125; <span class="keyword">as</span> s&#x27;) -&gt;</span><br><span class="line"> s&#x27;.spec &lt;- <span class="type">Complete</span> &#123; size = <span class="number">128</span>; align = <span class="number">8</span> &#125;</span><br><span class="line"> | <span class="type">Struct</span> (&#123; tag = <span class="string">&quot;sockaddr&quot;</span>; spec = <span class="type">Incomplete</span> _ &#125; <span class="keyword">as</span> s&#x27;) -&gt;</span><br><span class="line"> s&#x27;.spec &lt;- <span class="type">Complete</span> &#123; size = <span class="number">16</span>; align = <span class="number">1</span> &#125;</span><br><span class="line"> | <span class="type">Struct</span> &#123; tag; spec = <span class="type">Complete</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> tag)</span><br><span class="line"> | <span class="type">Union</span> &#123; utag; uspec = <span class="type">Some</span> _ &#125; -&gt;</span><br><span class="line"> raise (<span class="type">ModifyingSealedType</span> utag)</span><br><span class="line"> | <span class="type">View</span> &#123; ty &#125; -&gt; seal ty</span><br><span class="line"> | _ -&gt;</span><br><span class="line"> raise (<span class="type">Unsupported</span> <span class="string">&quot;Sealing a non-structured type&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="symbol">&#x27;a</span> const = <span class="symbol">&#x27;a</span></span><br><span class="line"><span class="keyword">let</span> constant (<span class="keyword">type</span> t) name (t : t typ) : t = <span class="keyword">match</span> t, name <span class="keyword">with</span></span><br><span class="line"> | _, s -&gt; failwith (<span class="string">&quot;unmatched constant: &quot;</span>^ s)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> enum (<span class="keyword">type</span> a) name ?typedef ?unexpected (alist : (a * <span class="built_in">int64</span>) <span class="built_in">list</span>) =</span><br><span class="line"> <span class="keyword">match</span> name <span class="keyword">with</span></span><br><span class="line"> | s -&gt;</span><br><span class="line"> failwith (<span class="string">&quot;unmatched enum: &quot;</span>^ s)</span><br></pre></td></tr></table></figure>
+
+<p>As you can see, this exports all the offsets required to access the fields inside a <code>sockaddr_t</code> structure. We’re now ready to move to the final stage, which is the actual binding stubs!</p>
+<h2 id="Binding-stubs"><a href="#Binding-stubs" class="headerlink" title="Binding stubs"></a>Binding stubs</h2><p>First step in this pass, just like with the previous ones, we need to configure <code>dune</code> to be able to build the exported <code>.ml</code> code from the <code>types</code> pass:</p>
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_types.ml)</span><br><span class="line"> (deps (:exec ../generator/exec.sh)</span><br><span class="line"> (:gen ../generator/gen_types_c))</span><br><span class="line"> (action (with-stdout-to %&#123;targets&#125;</span><br><span class="line"> (system &quot;%&#123;exec&#125; %&#123;ocaml-config:system&#125; %&#123;gen&#125;&quot;))))</span><br></pre></td></tr></table></figure>
+
+<p>And we can now define the proper bindings. Here’s how it looks like:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Def</span> (<span class="type">F</span> : <span class="type">Cstubs</span>.<span class="type">FOREIGN</span>) = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">open</span> <span class="type">F</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">module</span> <span class="type">Types</span> = <span class="type">Sys_socket_types</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_types</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">open</span> <span class="type">Types</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> getnameinfo = foreign <span class="string">&quot;getnameinfo&quot;</span> (ptr sockaddr_t @-&gt; socklen_t @-&gt; ptr <span class="built_in">char</span> @-&gt; socklen_t @-&gt; ptr <span class="built_in">char</span> @-&gt; socklen_t @-&gt; <span class="built_in">int</span> @-&gt; (returning <span class="built_in">int</span>))</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
+
+<p>As you can see, we’re exporting the <code>getnameinfo</code> function, taking various arguments, including a pointer to a <code>sockaddr_t</code> structure and a couple of <code>socklen_t</code> integers, making use of all the various data types and structures previously defined. The exact specifications of this function can be found <a href="https://pubs.opengroup.org/onlinepubs/009695399/functions/getnameinfo.html">here</a>. We can now define out top-level API..</p>
+<h2 id="Final-API"><a href="#Final-API" class="headerlink" title="Final API"></a>Final API</h2><p>Building upon the previous modules, we export various OCaml idiomatic APIs that the binding user can now use to build new bindings against the <code>socket.h</code> APIs.</p>
+<p>Just like with the previous steps, first we need to configure the build system:</p>
+<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_stubs.ml)</span><br><span class="line"> (deps (:gen ./generator/gen_stubs.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; ml %&#123;targets&#125;)))</span><br><span class="line"></span><br><span class="line">(rule</span><br><span class="line"> (targets sys_socket_generated_stubs.c)</span><br><span class="line"> (deps (:gen ./generator/gen_stubs.exe))</span><br><span class="line"> (action (run %&#123;gen&#125; c %&#123;targets&#125;)))</span><br></pre></td></tr></table></figure>
+
+<p>This time, we need <code>ocaml-ctypes</code> to generate two compilation units: a <code>.ml</code> file describing the API exported during the <code>stubs</code> phase, as well as the C code to glue it with the C APIs. Here’s the code for that generator:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> c_headers = <span class="string">&quot;</span></span><br><span class="line"><span class="string">#ifdef _WIN32</span></span><br><span class="line"><span class="string"> #include &lt;winsock2.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;ws2tcpip.h&gt;</span></span><br><span class="line"><span class="string">#else</span></span><br><span class="line"><span class="string"> #include &lt;sys/socket.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netinet/in.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;arpa/inet.h&gt;</span></span><br><span class="line"><span class="string"> #include &lt;netdb.h&gt;</span></span><br><span class="line"><span class="string">#endif</span></span><br><span class="line"><span class="string">#include &lt;string.h&gt;</span></span><br><span class="line"><span class="string">&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> =</span><br><span class="line"> <span class="keyword">let</span> mode = <span class="type">Sys</span>.argv.(<span class="number">1</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> fname = <span class="type">Sys</span>.argv.(<span class="number">2</span>) <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> oc = open_out_bin fname <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> format =</span><br><span class="line"> <span class="type">Format</span>.formatter_of_out_channel oc</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> fn =</span><br><span class="line"> <span class="keyword">match</span> mode <span class="keyword">with</span></span><br><span class="line"> | <span class="string">&quot;ml&quot;</span> -&gt; <span class="type">Cstubs</span>.write_ml</span><br><span class="line"> | <span class="string">&quot;c&quot;</span> -&gt;</span><br><span class="line"> <span class="type">Format</span>.fprintf format <span class="string">&quot;%s@\n&quot;</span> c_headers;</span><br><span class="line"> <span class="type">Cstubs</span>.write_c</span><br><span class="line"> | _ -&gt; <span class="keyword">assert</span> <span class="literal">false</span></span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> fn ~concurrency:<span class="type">Cstubs</span>.unlocked format ~prefix:<span class="string">&quot;sys_socket&quot;</span> (<span class="keyword">module</span> <span class="type">Sys_socket_stubs</span>.<span class="type">Def</span>);</span><br><span class="line"> <span class="type">Format</span>.pp_print_flush format <span class="literal">()</span>;</span><br><span class="line"> close_out oc</span><br></pre></td></tr></table></figure>
+
+<p>The exported <code>.ml</code> and <code>.c</code> files are omitted here for simplicity but the reader can generated them themselves from the <code>[ocaml-sys-socket](https://github.com/toots/ocaml-sys-socket)</code> repository if they are curious about their actual content.</p>
+<p>We can now export our top-level API:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="type">Sys_socket_types</span>.<span class="type">SaFamily</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">include</span> <span class="type">Sys_socket_stubs</span>.<span class="type">Def</span>(<span class="type">Sys_socket_generated_stubs</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> socklen = <span class="type">Types</span>.socklen</span><br><span class="line"><span class="keyword">let</span> socklen_t = <span class="type">Types</span>.socklen_t</span><br><span class="line"><span class="keyword">let</span> int_of_socklen = <span class="type">Types</span>.int_of_socklen</span><br><span class="line"><span class="keyword">let</span> socklen_of_int = <span class="type">Types</span>.socklen_of_int</span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> <span class="type">Sockaddr</span> = <span class="keyword">struct</span></span><br><span class="line"> <span class="keyword">include</span> <span class="type">Types</span>.<span class="type">Sockaddr</span></span><br><span class="line"> <span class="keyword">let</span> from_sockaddr_storage = from_sockaddr_storage t</span><br><span class="line"> <span class="keyword">let</span> sa_data_len = <span class="type">Types</span>.sa_data_len</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> getnameinfo sockaddr_ptr =</span><br><span class="line"> <span class="keyword">let</span> maxhost = <span class="type">Types</span>.ni_maxhost <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> s = allocate_n <span class="built_in">char</span> ~count:maxhost <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> maxserv = <span class="type">Types</span>.ni_maxserv <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> p = allocate_n <span class="built_in">char</span> ~count:maxserv <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">match</span> getnameinfo sockaddr_ptr (socklen_of_int (sizeof sockaddr_t))</span><br><span class="line"> s (socklen_of_int maxhost) </span><br><span class="line"> p (socklen_of_int maxserv)</span><br><span class="line"> (<span class="type">Types</span>.ni_numerichost <span class="keyword">lor</span></span><br><span class="line"> <span class="type">Types</span>.ni_numericserv) <span class="keyword">with</span></span><br><span class="line"> | <span class="number">0</span> -&gt;</span><br><span class="line"> <span class="keyword">let</span> host =</span><br><span class="line"> <span class="keyword">let</span> length =</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">Size_t</span>.to_int</span><br><span class="line"> (strnlen s (<span class="type">Unsigned</span>.<span class="type">Size_t</span>.of_int maxhost))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> string_from_ptr s ~length</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> port =</span><br><span class="line"> <span class="keyword">let</span> length =</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">Size_t</span>.to_int</span><br><span class="line"> (strnlen p (<span class="type">Unsigned</span>.<span class="type">Size_t</span>.of_int maxserv))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">let</span> port =</span><br><span class="line"> string_from_ptr p ~length</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> int_of_string port</span><br><span class="line"> <span class="keyword">with</span> _ -&gt;</span><br><span class="line"> <span class="keyword">match</span> getservbyname p null <span class="keyword">with</span></span><br><span class="line"> | ptr <span class="keyword">when</span> is_null ptr -&gt; failwith <span class="string">&quot;getnameinfo&quot;</span></span><br><span class="line"> | ptr -&gt;</span><br><span class="line"> <span class="type">Unsigned</span>.<span class="type">UInt16</span>.to_int</span><br><span class="line"> (ntohs (!@ (ptr |-&gt; <span class="type">Types</span>.<span class="type">Servent</span>.s_port)))</span><br><span class="line"> <span class="keyword">in</span></span><br><span class="line"> host, port</span><br><span class="line"> | _ -&gt; failwith <span class="string">&quot;getnameinfo&quot;</span></span><br><span class="line"></span><br><span class="line">...</span><br></pre></td></tr></table></figure>
+
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Ctypes</span></span><br><span class="line"></span><br><span class="line"><span class="comment">(** Ctypes routines for C type socklen_t. *)</span></span><br><span class="line"><span class="keyword">type</span> socklen</span><br><span class="line"><span class="keyword">val</span> socklen_t : socklen typ</span><br><span class="line"><span class="keyword">val</span> int_of_socklen : socklen -&gt; <span class="built_in">int</span></span><br><span class="line"><span class="keyword">val</span> socklen_of_int : <span class="built_in">int</span> -&gt; socklen</span><br><span class="line"></span><br><span class="line"><span class="comment">(** Generic sockaddr_t structure. *)</span></span><br><span class="line"><span class="keyword">module</span> <span class="type">Sockaddr</span> : <span class="keyword">sig</span></span><br><span class="line"> <span class="keyword">type</span> t</span><br><span class="line"> <span class="keyword">val</span> t : t structure typ</span><br><span class="line"> <span class="keyword">val</span> sa_family : (sa_family, t structure) field</span><br><span class="line"> <span class="keyword">val</span> sa_data : (<span class="built_in">char</span> carray, t structure) field</span><br><span class="line"> <span class="keyword">val</span> sa_data_len : <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">val</span> from_sockaddr_storage : <span class="type">SockaddrStorage</span>.t structure ptr -&gt; t structure ptr</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">(** IP address conversion functions. *)</span></span><br><span class="line"><span class="keyword">val</span> getnameinfo : sockaddr ptr -&gt; <span class="built_in">string</span> * <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line">...</span><br></pre></td></tr></table></figure>
+
+<p>That’s it! We now have <code>ocaml-ctypes</code> specific data types and structures that can be used to interface with the host’s native <code>socket.h</code> APIs. Note that we also worked on top of the original low-level binding to <code>getnameinfo</code> to export a higher-level function more idiomatic to the OCaml language.</p>
+<h1 id="Lagniappe-cross-compilation-to-Windows"><a href="#Lagniappe-cross-compilation-to-Windows" class="headerlink" title="Lagniappe: cross-compilation to Windows"></a>Lagniappe: cross-compilation to Windows</h1><p>On windows platforms, <code>liquidsoap</code> is compiled using <code>[ocaml-cross-windows](https://github.com/ocaml-cross/opam-cross-windows)</code> and, since windows does have compatible socket APIs, we wanted to also look at cross-compiling for the windows target, which is where we hit a snag on the current <code>dune</code> support.</p>
+<p>The problem is that, at each intermediary steps, in the case of a cross-compilation, the compiled binaries need to use the target’s OS headers and not the host’s headers, otherwise we end up using offsets specific to e.g. Debian but for a windows binary.</p>
+<p>In this case, this means that the compiled <code>.exe</code> binaries need to be windows binaries and that we need to execute them as windows native binaries, using <code>[wine](https://www.winehq.org/)</code> .</p>
+<p><code>dune</code> has a truly amazing <a href="https://dune.readthedocs.io/en/latest/cross-compilation.html">support for cross-compiling</a>, which we do not cover here, but, unfortunately, its primitives for building and executing binaries do not yet cover this use case. Thus we had to trick it into compiling things the way we wanted to do, which why we are using the <code>exec.sh</code> wrapper. Here’s its code:</p>
+<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line"><span class="meta">#!/bin/sh</span></span><br><span class="line"></span><br><span class="line">SYSTEM=<span class="variable">$1</span></span><br><span class="line">CMD=<span class="variable">$2</span></span><br><span class="line">ARG=<span class="variable">$3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">test</span> <span class="string">&quot;<span class="variable">$&#123;SYSTEM&#125;</span>&quot;</span> = <span class="string">&quot;mingw&quot;</span>; <span class="keyword">then</span></span><br><span class="line"> wine <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br><span class="line"><span class="keyword">elif</span> <span class="built_in">test</span> <span class="string">&quot;<span class="variable">$&#123;SYSTEM&#125;</span>&quot;</span> = <span class="string">&quot;mingw64&quot;</span>; <span class="keyword">then</span></span><br><span class="line"> wine64 <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"> <span class="variable">$CMD</span> <span class="variable">$ARG</span></span><br></pre></td></tr></table></figure>
+
+<p>Now, you can go back to the previous <code>dune</code> files and see how this wrapper allows to execute binaries according to the system that the corresponding <code>ocamlopt</code> compiler has been configured to build for.</p>
+<h1 id="Conclusion"><a href="#Conclusion" class="headerlink" title="Conclusion"></a>Conclusion</h1><p>It’s been a fun time working on this binding! It’s amazing to see the level of details that can be built through <code>ocaml-ctypes</code> using their provided primitives. Ultimately, the binding is very clean and elegant, with very few low-level assumptions.</p>
+<p>Likewise, the simplicity and power of the <code>dune</code> build system makes this very fluid to build. Without it, each of the described steps above would have been much more painful to execute and compile.</p>
+<p>[1]: My bet is that, at the time the POSIX specifications were being written, there we already several inconsistent <code>socket.h</code> headers out in the wild among the various historical UNIX flavors..</p>
+]]></content>
+ <tags>
+ <tag>Technique</tag>
+ <tag>OCaml</tag>
+ <tag>Archive</tag>
+ </tags>
+ </entry>
+ <entry>
<title>C++ 20 实现 string split</title>
<url>/2023/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/</url>
<content><![CDATA[<p>C++20引入了范围库ranges,其中提供的两个范围适配器std::split、std::lazy_split可以使我们以一种更为优雅的形式实现split:</p>
@@ -129,7 +230,10 @@
<entry>
<title>Functional Reactive Programming in F#</title>
<url>/2024/09/12/Functional-Reactive-Programming-in-F/</url>
- <content><![CDATA[<p>Events are everywhere. Almost every program has to handle events, whether it be button clicks in the user interface, listening to sockets in a server, or even a system shutdown notification.</p>
+ <content><![CDATA[<blockquote>
+<p><a href="https://fsharpforfunandprofit.com/posts/concurrency-reactive/">https://fsharpforfunandprofit.com/posts/concurrency-reactive/</a></p>
+</blockquote>
+<p>Events are everywhere. Almost every program has to handle events, whether it be button clicks in the user interface, listening to sockets in a server, or even a system shutdown notification.</p>
<p>And events are the basis of one of the most common OO design patterns: the “Observer” pattern.</p>
<p>But as we know, event handling, like concurrency in general, can be tricky to implement. Simple event logic is straightforward, but what about logic like “do something if two events happen in a row but do something different if only one event happens” or “do something if two events happen at roughly the same time”. And how easy is it to combine these requirements in other, more complex ways?</p>
<p>Even if you can successfully implement these requirements, the code tends to be spaghetti like and hard to understand, even with the best intentions.</p>
@@ -246,6 +350,7 @@
]]></content>
<tags>
<tag>Technique</tag>
+ <tag>Archive</tag>
<tag>F#</tag>
</tags>
</entry>
@@ -2725,6 +2830,32 @@
</tags>
</entry>
<entry>
+ <title>肩周炎和肩袖损伤的区别</title>
+ <url>/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/</url>
+ <content><![CDATA[<p>在肩痛患者中,只有2%~5%是肩周炎,肩袖损伤更为常见,占30%~40%。</p>
+<p>肩周炎和肩袖损伤都是临床上常见的疾病。很多肩痛患者认为自己患有肩周炎,坚持做肩关节活动训练,但一直没有缓解,且逐渐加重,甚至影响了睡眠和生活,遂至医院就诊,经过影像学检查确诊为肩袖损伤。这是因为肩周炎和肩袖损伤均可引起肩痛,严重时均可出现夜间疼痛,甚至影响睡眠,症状相似,故极易混淆。</p>
+<p>肩周炎是肩关节冻结、活动受限,遇风、寒冷加重,是肩周软组织(包括肩周肌、肌腱、滑囊和关节囊等)病变引起的以肩关节疼痛和功能障碍为特征的疾病。</p>
+<p>肩袖损伤是由退行性病变或外力等导致肩袖的4块肌肉、肌腱发生病变,进而导致肩关节局部疼痛、活动受限的疾病。</p>
+<p>许多肩袖损伤患者无明确的外伤史,而是由长期做过顶运动、提重物或上肢长期固定于一个姿势引起的。</p>
+<ul>
+<li><p>肩周炎的疼痛范围广,涉及整个肩关节,肩袖损伤引起的疼痛多出现在肩前方、外上方</p>
+</li>
+<li><p>肩周炎的压痛点多而广,肩袖损的伤压痛点多出现在肩前方、上方及肩胛骨外侧缘。</p>
+</li>
+<li><p>肩周炎患者对气候变化较为敏感,肩袖损伤患者对气候变化不敏感,对劳累、提重物及做过顶运动较为敏感。</p>
+</li>
+<li><p>肩周炎患者活动受限范围广,肩袖损伤患者多以肩关节外展活动受限为主,同时伴有外展无力。</p>
+</li>
+<li><p>肩周炎患者进行上举过顶运动训练后活动范围会好转,症状会减轻;而肩袖损伤患者进行上举过顶运动训练后疼痛加重。</p>
+</li>
+</ul>
+]]></content>
+ <tags>
+ <tag>Medicine</tag>
+ <tag>Life</tag>
+ </tags>
+ </entry>
+ <entry>
<title>肺炎支原体注意事项</title>
<url>/2023/10/25/%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</url>
<content><![CDATA[<ol>
diff --git a/tag/index.html b/tag/index.html
index 58762173..9c8f19ab 100644
--- a/tag/index.html
+++ b/tag/index.html
@@ -158,20 +158,26 @@
</span>
<span class="post-tag">
- <a href="/tags/C/">
- C++
+ <a href="/tags/OCaml/">
+ OCaml
</a>
</span>
<span class="post-tag">
- <a href="/tags/F/">
- F#
+ <a href="/tags/Archive/">
+ Archive
</a>
</span>
<span class="post-tag">
- <a href="/tags/OCaml/">
- OCaml
+ <a href="/tags/C/">
+ C++
+ </a>
+ </span>
+
+ <span class="post-tag">
+ <a href="/tags/F/">
+ F#
</a>
</span>
diff --git a/tags/Archive/index.html b/tags/Archive/index.html
new file mode 100644
index 00000000..f58ef5eb
--- /dev/null
+++ b/tags/Archive/index.html
@@ -0,0 +1,246 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport"
+ content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+<title>Tag: Archive | 暮秋小屋</title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+<style>
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
+</style>
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script src="/js/frame.js"></script>
+
+
+
+
+
+ <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
+ <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+
+
+
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="mask-border">
+ </div>
+
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ Menu
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">主页</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">日记本</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">医学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">计算机科学</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">生活</a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">关于</a>
+ </li>
+
+
+
+ <li class="menu-item search-btn">
+ <a href="#">Search</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <div id="tag">
+
+
+ <p class="tag-title">
+ / <a href="/tag/">tags</a>
+ / <a href="">Archive</a> /
+ </p>
+ <div class="post-list">
+
+
+
+
+
+
+ <div class="year-title">2024</div>
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
+
+ Advanced C binding using ocaml-ctypes and dune
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
+
+ Functional Reactive Programming in F#
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 12, 2024</span>
+ </div>
+
+
+ <div id="paginator">
+
+ </div>
+</div>
+
+
+
+
+</div>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+ </div>
+
+
+ <div class="search-popup">
+ <div class="search-popup-overlay">
+ </div>
+ <div class="search-popup-window" >
+ <div class="search-header">
+ <div class="search-input-container">
+ <input autocomplete="off" autocapitalize="off" maxlength="80"
+ placeholder="Search Anything" spellcheck="false"
+ type="search" class="search-input">
+ </div>
+ <div class="search-close-btn">
+ <div class="icon close-btn"></div>
+ </div>
+ </div>
+ <div class="search-result-container">
+ </div>
+ </div>
+</div>
+
+<script>
+ const searchConfig = {
+ path : "/search.xml",
+ top_n_per_article: "1",
+ unescape : "false",
+ trigger: "auto",
+ preload: "false"
+ }
+</script>
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/search.js"></script>
+<script src="/js/search.js"></script>
+
+
+
+ </body>
+</html>
diff --git a/tags/Life/index.html b/tags/Life/index.html
index 950747fc..f498e9af 100644
--- a/tags/Life/index.html
+++ b/tags/Life/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
+
+ 肩周炎和肩袖损伤的区别
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/08/%E4%B8%AD%E8%80%81%E5%B9%B4%E4%BA%BA%E6%B2%89%E8%BF%B7%E6%89%8B%E6%9C%BA%E7%9A%84%E9%97%AE%E9%A2%98/">
中老年人沉迷手机的问题
@@ -308,24 +326,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/06/22/%E7%81%AF%E7%AC%BC%E8%8D%89/">
-
- 灯笼草
-
- </a>
- </div>
-
- <span class="post-date">Jun 22, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Life/page/2/index.html b/tags/Life/page/2/index.html
index 8e463a18..3469f3a3 100644
--- a/tags/Life/page/2/index.html
+++ b/tags/Life/page/2/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/06/22/%E7%81%AF%E7%AC%BC%E8%8D%89/">
+
+ 灯笼草
+
+ </a>
+ </div>
+
+ <span class="post-date">Jun 22, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/06/17/%E5%8F%91%E7%83%AD%E5%8F%8A%E8%B6%85%E9%AB%98%E7%83%AD%E5%8D%B1%E8%B1%A1/">
发热及超高热危象
diff --git a/tags/Medicine/index.html b/tags/Medicine/index.html
index 3c43a9aa..3cb2c684 100644
--- a/tags/Medicine/index.html
+++ b/tags/Medicine/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
+
+ 肩周炎和肩袖损伤的区别
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
藿香正气水和藿香正气口服液的区别
@@ -308,24 +326,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
-
- Radiographic Absence of the Left Humeral Head
-
- </a>
- </div>
-
- <span class="post-date">Oct 25, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/2/index.html b/tags/Medicine/page/2/index.html
index 25976053..185451f5 100644
--- a/tags/Medicine/page/2/index.html
+++ b/tags/Medicine/page/2/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
+
+ Radiographic Absence of the Left Humeral Head
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 25, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/10/25/%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/">
肺炎支原体注意事项
@@ -306,24 +324,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
-
- 奥司他韦
-
- </a>
- </div>
-
- <span class="post-date">Mar 5, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/3/index.html b/tags/Medicine/page/3/index.html
index 58da56ac..7417df94 100644
--- a/tags/Medicine/page/3/index.html
+++ b/tags/Medicine/page/3/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
+
+ 奥司他韦
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 5, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
金匮要略
diff --git a/tags/OCaml/index.html b/tags/OCaml/index.html
index aca63b5a..f131e82c 100644
--- a/tags/OCaml/index.html
+++ b/tags/OCaml/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
+
+ Advanced C binding using ocaml-ctypes and dune
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/07/23/OCaml-News-2024-6/">
OCaml News 2024-6
@@ -308,24 +326,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
-
- 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
-
- </a>
- </div>
-
- <span class="post-date">Jun 28, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/OCaml/page/2/index.html b/tags/OCaml/page/2/index.html
index d067e0cc..ff4f3771 100644
--- a/tags/OCaml/page/2/index.html
+++ b/tags/OCaml/page/2/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/06/28/%E9%9A%90%E8%97%8F%E4%B8%80%E4%BA%9BOCaml-Effect%E7%9A%84%E6%9C%BA%E5%88%B6%EF%BC%8C%E8%AE%A9%E5%85%B6%E8%AF%AD%E6%B3%95%E5%9C%A8%E7%B2%BE%E7%A5%9E%E4%B8%8A%E6%9B%B4%E6%8E%A5%E8%BF%91delimcc/">
+
+ 隐藏一些OCaml Effect的机制,让其语法在精神上更接近delimcc
+
+ </a>
+ </div>
+
+ <span class="post-date">Jun 28, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/06/28/caml-release-runtime-system%E5%AF%BC%E8%87%B4%E7%9A%84%E6%AD%BB%E9%94%81%E9%97%AE%E9%A2%98/">
caml_release_runtime_system导致的死锁问题
diff --git a/tags/Technique/index.html b/tags/Technique/index.html
index 6f91cbd5..8b2adba3 100644
--- a/tags/Technique/index.html
+++ b/tags/Technique/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/Advanced-C-binding-using-ocaml-ctypes-and-dune/">
+
+ Advanced C binding using ocaml-ctypes and dune
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
Functional Reactive Programming in F#
@@ -306,24 +324,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/01/18/OCaml-News-2024-2/">
-
- OCaml News 2024-2
-
- </a>
- </div>
-
- <span class="post-date">Jan 18, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Technique/page/2/index.html b/tags/Technique/page/2/index.html
index 0177dd5c..b652ddf0 100644
--- a/tags/Technique/page/2/index.html
+++ b/tags/Technique/page/2/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/01/18/OCaml-News-2024-2/">
+
+ OCaml News 2024-2
+
+ </a>
+ </div>
+
+ <span class="post-date">Jan 18, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/01/08/OCaml-News-2024-1/">
OCaml News 2024-1
@@ -308,24 +326,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
-
- Rust 闭包 lifetime may not live long enough 问题
-
- </a>
- </div>
-
- <span class="post-date">May 24, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Technique/page/3/index.html b/tags/Technique/page/3/index.html
index c0d5395c..efdf01f8 100644
--- a/tags/Technique/page/3/index.html
+++ b/tags/Technique/page/3/index.html
@@ -151,6 +151,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
+
+ Rust 闭包 lifetime may not live long enough 问题
+
+ </a>
+ </div>
+
+ <span class="post-date">May 24, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/05/12/C-20-%E5%AE%9E%E7%8E%B0-string-split/">
C++ 20 实现 string split