C和Go相互调用

aiat5431 5年前
   <p>C可以调用Go,并且Go可以调用C, 如果更进一步呢, C-->Go-->C 或者 Go-->C-->Go 的调用如何实现?</p>    <p>本文通过两个简单的例子帮助你了解这两种复杂的调用关系。本文不涉及两者之间的复杂的数据转换,官方文章 <a href="/misc/goto?guid=4959730284455884938" rel="nofollow,noindex">C? Go? Cgo!</a> 、 <a href="/misc/goto?guid=4959730284536450207" rel="nofollow,noindex">wiki/cgo</a> 和 <a href="/misc/goto?guid=4959758074574008490" rel="nofollow,noindex">cmd/cgo</a> 有一些介绍。</p>    <h2>Go-->C-->Go</h2>    <p>Go程序调用C实现的函数,然后C实现的函数又调用Go实现的函数。</p>    <p>1、首先,我们新建一个 hello.go 的文件:</p>    <p>hello.go</p>    <table>     <tbody>      <tr>       <td> <pre>  <code class="language-go">package main    import "C"  import "fmt"    //export HelloFromGo  func HelloFromGo() {   fmt.Printf("Hello from Go!\n")  }  </code></pre> </td>      </tr>     </tbody>    </table>    <p>它定义了一个 HelloFromGo 函数,注意这个函数是一个纯的Go函数,我们定义它的输出符号为 HelloFromGo 。</p>    <p>2、接着我们新建一个 hello.c 的文件:</p>    <p>hello.c</p>    <table>     <tbody>      <tr>       <td> <pre>  <code class="language-go">#include <stdio.h>  #include "_cgo_export.h"    int helloFromC() {   printf("Hi from C\n");   //call Go function   HelloFromGo();   return 0;  }  </code></pre> </td>      </tr>     </tbody>    </table>    <p>这个c文件定义了一个C函数 helloFromC ,内部它会调用我们刚才定义的 HelloFromGo 函数。</p>    <p>这样,我们实现了 C 调用 Go : C-->Go ,下面我们再实现Go调用C。</p>    <p>3、最后新建一个 main.go 文件:</p>    <p>main.go</p>    <table>     <tbody>      <tr>       <td> <pre>  <code class="language-go">package main    /*  extern int helloFromC();  */  import "C"    func main() {   //call c function   C.helloFromC()  }  </code></pre> </td>      </tr>     </tbody>    </table>    <p>它调用第二步实现的C函数 helloFromC 。</p>    <p>运行测试一下:</p>    <pre>  <code class="language-go">$ go run .  Hi from C  Hello from Go!  </code></pre>    <p>可以看到,期望的函数调用正常的运行。第一行是C函数的输出,第二行是Go函数的输出。</p>    <h2>C-->Go-->C</h2>    <p>第二个例子演示了C程序调用Go实现的函数,然后Go实现的函数又调用C实现的函数。</p>    <p>1、首先新建一个 hello.c 文件:</p>    <p>hello.c</p>    <table>     <tbody>      <tr>       <td> <pre>  <code class="language-go">#include <stdio.h>    int helloFromC() {   printf("Hi from C\n");   return 0;  }  </code></pre> </td>      </tr>     </tbody>    </table>    <p>它定义了一个纯C实现的函数。</p>    <p>2、接着新建一个 hello.go 文件:</p>    <pre>  <code class="language-go">// go build -o hello.so -buildmode=c-shared .  package main    /*  extern int helloFromC();  */  import "C"    import "fmt"    //export HelloFromGo  func HelloFromGo() {   fmt.Printf("Hello from Go!\n")   C.helloFromC()  }    func main() {    }  </code></pre>    <p>它实现了一个Go函数 HelloFromGo ,内部实现调用了C实现的函数 helloFromC ,这样我们就实现了 Go-->C 。</p>    <p>注意包名设置为 package main ,并且增加一个空的 main 函数。</p>    <p>运行 go build -o hello.so -buildmode=c-shared . 生成一个C可以调用的库,这调命令执行完后会生成 hello.so 文件和 hello.h 文件。</p>    <p>3、最后新建一个文件夹,随便起个名字,比如 main</p>    <p>将刚才生成的 hello.so 文件和 hello.h 文件复制到 main 文件夹,并在 main 文件夹中新建一个文件 main.c :</p>    <p>main.c</p>    <table>     <tbody>      <tr>       <td> <pre>  <code class="language-go">#include <stdio.h>  #include "hello.h"    int main() {   printf("use hello lib from C:\n");      HelloFromGo();      return 0;  }  </code></pre> </td>      </tr>     </tbody>    </table>    <p>运行 gcc -o main main.c hello.so 生成可执行文件 main , 运行 main :</p>    <pre>  <code class="language-go">$ ./main  use hello lib from C:  Hello from Go!  Hi from C  </code></pre>    <p>第一行输出来自 main.c ,第二行来自Go函数,第三行来自 hello.c 中的C函数,这样我们就实现了 C-->Go--C 的复杂调用。</p>    <h3>参考文档</h3>    <ol>     <li><a href="/misc/goto?guid=4959758074661073659" rel="nofollow,noindex">https://medium.com/using-go-in-mobile-apps/using-go-in-mobile-apps-part-1-calling-go-functions-from-c-be1ecf7dfbc6</a></li>     <li><a href="/misc/goto?guid=4959758074756250968" rel="nofollow,noindex">https://github.com/vladimirvivien/go-cshared-examples</a></li>     <li><a href="/misc/goto?guid=4959758074574008490" rel="nofollow,noindex">http://golang.org/cmd/cgo</a></li>     <li><a href="/misc/goto?guid=4959758074859304153" rel="nofollow,noindex">https://gist.github.com/zchee/b9c99695463d8902cd33</a></li>     <li><a href="/misc/goto?guid=4959758074940181206" rel="nofollow,noindex">https://medium.com/@liamkelly17/working-with-packed-c-structs-in-cgo-224a0a3b708b</a></li>    </ol>    <p> </p>    <p>来自:https://colobu.com/2018/08/28/c-and-go-calling-interaction/</p>    <p> </p>