精华内容
下载资源
问答
  • <p>I'm trying to call a golang function from my C code. Golang does not use the standard x86_64 calling convention, so I have to resort to implementing the transition myself. As gcc does not want to ...
  •  按照如上写法,在C代码中依次调用,在执行Func1时还算ok,但是在执行到Func2时,则报了h.stream内存地址非法的错误,暂时还不明白stream在哪被gc了,还望各位赐教。  另外,如下代码则没问题。 //export ...

          项目需求,复用了一段之前写过的Go代码,利用Go 1.5的新功能导出了一个可以给C语言使用的动态库。由于目前Go的结构体还不支持直接导出到C,因此使用了interface{}作为过渡。结构体以及导出函数定义如下

    type Handler struct{
        stream *Stream
        p      *Parser
    }
    
    //export NewHandler
    func NewHandler() interface{}{
        return Handler{
          //成员变量初始化
        }
    }
    
    //export Func1
    func Func1(handler interface{}){
      if h, ok := handler.(Handler);ok{
          //访问stream成员
          foo1(h.stream)
      }
    }
    
    //export Func2
    func Func2(handler interface{}){
      if h, ok := handler.(Handler);ok{
          //访问stream成员
          foo2(h.stream)
      }
    }

          按照如上写法,在C代码中依次调用,在执行Func1时还算ok,但是在执行到Func2时,则报了h.stream内存地址非法的错误,暂时还不明白stream在哪被gc了,还望各位赐教。

          另外,如下代码则没问题。

    //export NewHandler
    func NewHandler() interface{}{
        return &Handler{
          //成员变量初始化
        }
    }
    
    //export Func1
    func Func1(handler interface{}){
      if h, ok := handler.(*Handler);ok{
          //访问stream成员
          foo1(h.stream)
      }
    }
    
    //export Func2
    func Func2(handler interface{}){
      if h, ok := handler.(*Handler);ok{
          //访问stream成员
          foo2(h.stream)
      }
    }

    更新1: 2015.12.30 测试结果表明,改为指针也不能有效解决该问题,仍然会出现内存地址非法情况,看来是Go里面的对象导出给C使用后,gc对该对象的跟踪出了问题,导致在C里边还在使用该对象时却被Go里边回收了。

    更新2: 由于是被Go内部gc,考虑在Go代码增加一对象池防止对象被gc,另外考虑到给不熟悉Go的使用C的童鞋,此处返回unsafe.Pointer代替之前的interface{},更改后的逻辑如下

    var(
     	obj_pool = map[unsafe.Pointer]*Handler{}
    	lock     = make(chan bool, 1)
    )
    
    type Handler struct{
        stream *Stream
        p      *Parser
    }
    
    //export NewHandler
    func NewHandler() unsafe.Pointer{
        p:= &Handler{
          //成员变量初始化
        }
        lock <- true
        defer func() { <-lock }()
        obj_pool[unsafe.Pointer(p)] = p
        return unsafe.Pointer(p)    
    }
    
    //其他导出函数...
    //......
    
    //export ReleaseHandler
    func ReleaseHandler(handler unsafe.Pointer){
         lock <- true
         defer func() { <-lock }()
         if _, ok := obj_pool[handler]; ok {
    	 delete(obj_pool, handler)
         }
    }

          增加对象池后,之前的Go导出对象被gc的问题基本上已经没看到了,相当于变相在Go里面增加对象引用以防止被gc。此外,为了防止资源泄露,采用对象池的方法处理后,自然需要添加一个释放对象的逻辑,于是增加ReleaseHandler方法。

    转载于:https://my.oschina.net/BiaoLei/blog/552925

    展开全文
  • C/C++调用Golang

    2017-09-07 19:40:00
    C/C++调用Golang 二 《C/C++调用Golang 一》简单介绍了C/C++调用Golang的方法步骤,只涉及一个简单的函数调用。本文总结具体项目中的使用场景,将介绍三种较复杂的调用方式:一,C++向golang传入复杂结构体;二,...

    C/C++调用Golang

    C/C++调用Golang 一》简单介绍了C/C++调用Golang的方法步骤,只涉及一个简单的函数调用。本文总结具体项目中的使用场景,将介绍三种较复杂的调用方式:一,C++golang传入复杂结构体;二,C++golang传入回调函数,在golang中调用C++函数;三,C++调用golang函数,返回复杂的结构体。

    (本文后面涉及三个例子,省略了编译步骤,仅展示关键代码。具体操作步骤参考《C/C++调用Golang 一》)

    C++golang传入复杂结构体

    采用avro来序列化与反序列化结构体。C++avro使用官方版本,golangavro使用gopkg.in/alanctgardner/gogen-avro.v4 。(C++代码省略了avro结构体的序列化与反序列化,仅展示C++Golang的交互部分)

     

    1.1 Golang 代码

    package main

     

    import "C"

    import "fmt"

     

    //export WriteData

    func WriteData(data []byte) int {

        fmt.Println("WriteData ", data, len(data))

        return 0

    }

     

    func main() {

     

    }

     

     

     

    编译生成的头文件

     

    /* Created by "go tool cgo" - DO NOT EDIT. */

     

    /* package c_references_to_go/sample1 */

     

    /* Start of preamble from import "C" comments.  */

     

     

     

     

    /* End of preamble from import "C" comments.  */

     

     

    /* Start of boilerplate cgo prologue.  */

    #line 1 "cgo-gcc-export-header-prolog"

     

    #ifndef GO_CGO_PROLOGUE_H

    #define GO_CGO_PROLOGUE_H

     

    typedef signed char GoInt8;

    typedef unsigned char GoUint8;

    typedef short GoInt16;

    typedef unsigned short GoUint16;

    typedef int GoInt32;

    typedef unsigned int GoUint32;

    typedef long long GoInt64;

    typedef unsigned long long GoUint64;

    typedef GoInt32 GoInt;

    typedef GoUint32 GoUint;

    //typedef __SIZE_TYPE__ GoUintptr;

    typedef float GoFloat32;

    typedef double GoFloat64;

    //typedef float _Complex GoComplex64;

    //typedef double _Complex GoComplex128;

     

    /*

      static assertion to make sure the file is being used on architecture

      at least with matching size of GoInt.

    */

    typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];

     

    typedef struct { const char *p; GoInt n; } GoString;

    typedef void *GoMap;

    typedef void *GoChan;

    typedef struct { void *t; void *v; } GoInterface;

    typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

     

    #endif

     

    /* End of boilerplate cgo prologue.  */

     

    #ifdef __cplusplus

    extern "C" {

    #endif

     

     

    extern GoInt WriteData(GoSlice p0);

     

    #ifdef __cplusplus

    }

    #endif

     

     

    1.2 C++代码

    #include <Windows.h>

    #include <stdio.h>

    #include "sample1.h"

     

    //#include "LargeStruct.h"

     

    typedef GoInt (*funcPtrWriteData)(GoSlice p0);

     

     

     

     

     

    int main(){

     

    HMODULE h = LoadLibraryA("sample1.dll");

    if (NULL == h || INVALID_HANDLE_VALUE == h)

    {

    return -1;

    }

     

    funcPtrWriteData pfWriteData = (funcPtrWriteData)GetProcAddress(h,"WriteData");

     

     

     

    if (pfWriteData)

    {

    /* LargeStruct ls;

    ls.ID = "100001";

    ls.Name = "Peter";

     

    Pet pet;

    pet.Type = "Dog";

    pet.Name = "WangCai";

    pet.Age = 5;

    ls.Pets.push_back(pet);*/

     

    GoSlice p0;

    p0.data = 0;  //serial ls to binary

    p0.len = p0.cap = 0;  //binary len

    pfWriteData(p0);

    }

     

     

    FreeLibrary(h);

    return 0;

    }

     

     

    C++golang传入回调函数

    2.1 Golang 代码

    设置回调需要中间的桥接函数 CReportData

     

    package main

     

    import (

        "fmt"

    )

     

    /*

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    typedef int (*ptfFuncReportData)(const char* data,int len);

    extern int CReportData(ptfFuncReportData pf,const char* data,int len);

     

    */

    import "C"

    import (

        "bytes"

        "c_references_to_go/sample3/avro_struct"

        "unsafe"

    )

     

    var callBackFunc C.ptfFuncReportData

     

    //export SetCallBack

    func SetCallBack(f C.ptfFuncReportData) {

        callBackFunc = f

    }

     

    //export BeginWork

    func BeginWork() {

        go func() {

            for index := 0; index < 10; index++ {

                var ls avro_struct.LargeStruct

     

                ls.ID = fmt.Sprintf("ID%d", 1000+index)

                ls.Name = fmt.Sprintf("Peter%d", index)

                ls.Pets = []*avro_struct.Pet{&avro_struct.Pet{Type: "Dog", Name: "WangCai", Age: 5}}

     

                var buf bytes.Buffer

                ls.Serialize(&buf)

                dataSlice := buf.Bytes()

     

                GoReportData(dataSlice)

            }

        }()

    }

     

    func GoReportData(data []byte) {

     

        C.CReportData(callBackFunc, (*C.char)(unsafe.Pointer(&data[0])), C.int(len(data)))

    }

     

    func main() {

     

    }

     

     

    bridge.c

     

     

    #include "_cgo_export.h"

     

    int CReportData(ptfFuncReportData pf,const char* data,int len){

        return pf(data,len);

    }



    编译后产生的头文件

     

    /* Created by "go tool cgo" - DO NOT EDIT. */

     

    /* package c_references_to_go/sample2 */

     

    /* Start of preamble from import "C" comments. */

     

    #line 7 "Y:\\mygo\\src\\c_references_to_go\\sample2\\main.go"

     

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    typedef int (*ptfFuncReportData)(const char* data,int len);

    extern int CReportData(ptfFuncReportData pf,const char* data,int len);

     

    #line 1 "cgo-generated-wrapper"

     

    /* End of preamble from import "C" comments. */

     

    /* Start of boilerplate cgo prologue. */

    #line 1 "cgo-gcc-export-header-prolog"

     

    #ifndef GO_CGO_PROLOGUE_H

    #define GO_CGO_PROLOGUE_H

     

    typedef signed char GoInt8;

    typedef unsigned char GoUint8;

    typedef short GoInt16;

    typedef unsigned short GoUint16;

    typedef int GoInt32;

    typedef unsigned int GoUint32;

    typedef long long GoInt64;

    typedef unsigned long long GoUint64;

    typedef GoInt32 GoInt;

    typedef GoUint32 GoUint;

    typedef __SIZE_TYPE__ GoUintptr;

    typedef float GoFloat32;

    typedef double GoFloat64;

    typedef float _Complex GoComplex64;

    typedef double _Complex GoComplex128;

     

    /*

    static assertion to make sure the file is being used on architecture

    at least with matching size of GoInt.

    */

    typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];

     

    typedef struct { const char *p; GoInt n; } GoString;

    typedef void *GoMap;

    typedef void *GoChan;

    typedef struct { void *t; void *v; } GoInterface;

    typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

     

    #endif

     

    /* End of boilerplate cgo prologue. */

     

    #ifdef __cplusplus

    extern "C" {

    #endif

     

    extern void SetCallBack(ptfFuncReportData p0);

     

    extern void BeginWork();

     

    #ifdef __cplusplus

    }

    #endif

     

     

     

     

    2.2 C++代码

    #include <Windows.h>

    #include <stdio.h>

    #include "sample2.h"

     

    typedef void (*funcPtrSetCallBack)(ptfFuncReportData p0);

    typedef void (*funcPtrBeginWork)();

     

     

    int OnReportData(const char* data,int len){

    printf("OnReportData %x %d\r\n",data,len);

    return 0;

    }

     

     

    int main(){

     

    HMODULE h = LoadLibraryA("sample2.dll");

    if (NULL == h || INVALID_HANDLE_VALUE == h)

    {

    return -1;

    }

     

    funcPtrSetCallBack pfSetCallBack = (funcPtrSetCallBack)GetProcAddress(h,"SetCallBack");

    funcPtrBeginWork pfBeginWork = (funcPtrBeginWork)GetProcAddress(h,"BeginWork");

     

     

    if (pfSetCallBack)

    {

    pfSetCallBack(OnReportData);

    }

     

        if (pfBeginWork)

        {

    pfBeginWork();

        }

     

    Sleep(1000*10);

     

    FreeLibrary(h);

    return 0;

    }

     

     

    运行之后的输出:

     

     

     

     

     

    C++调用golang函数返回复杂结构体

    不能向C++程序返回Go sliceGo struct。(详情见master分支 src/cmd/cgo/doc.go ,参考5

     

    3.1 Golang代码

    package main

     

    import (

        "bytes"

        "unsafe"

    )

     

    /*

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

     

    typedef struct {

         char* Data;

         int DataLen;

    } GetLargeStruct_return;

     

    extern GetLargeStruct_return* CopyLargeSturct(char* data,int dataLen);

    extern void FreeLargeSturct(GetLargeStruct_return* ptr);

     

    */

    import "C"

     

    import (

        "c_references_to_go/sample3/avro_struct"

    )

     

    //export GetLargeStruct

    func GetLargeStruct(paraIn int) *C.GetLargeStruct_return {

        var ls avro_struct.LargeStruct

     

        ls.ID = "1000001"

        ls.Name = "Peter"

        ls.Pets = []*avro_struct.Pet{&avro_struct.Pet{Type: "Dog", Name: "WangCai", Age: 5}}

     

        var buf bytes.Buffer

        ls.Serialize(&buf)

        dataSlice := buf.Bytes()

     

        return C.CopyLargeSturct((*C.char)(unsafe.Pointer(&dataSlice[0])), C.int(len(dataSlice)))

    }

     

    //export FreeLargeStruct

    func FreeLargeStruct(ptr *C.GetLargeStruct_return) {

        C.FreeLargeSturct(ptr)

    }

     

    //export GetLargeStruct2

    func GetLargeStruct2(paraIn int) (*C.char, int) {

        var ls avro_struct.LargeStruct

     

        ls.ID = "1000001"

        ls.Name = "Peter"

        ls.Pets = []*avro_struct.Pet{&avro_struct.Pet{Type: "Dog", Name: "WangCai", Age: 5}}

     

        var buf bytes.Buffer

        ls.Serialize(&buf)

        dataSlice := buf.Bytes()

     

        return (*C.char)(unsafe.Pointer(C.CBytes(dataSlice))), len(dataSlice)

    }

     

    //export FreeCBytes

    func FreeCBytes(ptr *C.char) {

        C.free(unsafe.Pointer(ptr))

    }

     

    func main() {

     

    }

     

     

     

    C函数源码文件 (释放C分配的内存)

     

     

    #include "_cgo_export.h"

     

    GetLargeStruct_return* CopyLargeSturct(char* data,int dataLen){

         GetLargeStruct_return* result = (GetLargeStruct_return*)malloc(sizeof(GetLargeStruct_return));

         result->DataLen = dataLen;

         result->Data = 0;

         if(dataLen>0){

         result->Data = malloc(dataLen);

         memcpy(result->Data,data,dataLen);

         }

     

         return result;

    }

     

    void FreeLargeSturct(GetLargeStruct_return* ptr){

         if(ptr != 0){

             if(ptr->Data != 0 ){

                 free(ptr->Data);

             }

             free(ptr);

         }

    }

     

    编译后产生的头文件

     

    /* Created by "go tool cgo" - DO NOT EDIT. */

     

    /* package c_references_to_go/sample3 */

     

    /* Start of preamble from import "C" comments. */

     

    #line 8 "Y:\\mygo\\src\\c_references_to_go\\sample3\\main.go"

     

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

     

    typedef struct {

       char* Data;

       int DataLen;

    } GetLargeStruct_return;

     

    extern GetLargeStruct_return* CopyLargeSturct(char* data,int dataLen);

    extern void FreeLargeSturct(GetLargeStruct_return* ptr);

     

    #line 1 "cgo-generated-wrapper"

     

    /* End of preamble from import "C" comments. */

     

    /* Start of boilerplate cgo prologue. */

    #line 1 "cgo-gcc-export-header-prolog"

     

    #ifndef GO_CGO_PROLOGUE_H

    #define GO_CGO_PROLOGUE_H

     

    typedef signed char GoInt8;

    typedef unsigned char GoUint8;

    typedef short GoInt16;

    typedef unsigned short GoUint16;

    typedef int GoInt32;

    typedef unsigned int GoUint32;

    typedef long long GoInt64;

    typedef unsigned long long GoUint64;

    typedef GoInt32 GoInt;

    typedef GoUint32 GoUint;

    typedef __SIZE_TYPE__ GoUintptr;

    typedef float GoFloat32;

    typedef double GoFloat64;

    typedef float _Complex GoComplex64;

    typedef double _Complex GoComplex128;

     

    /*

    static assertion to make sure the file is being used on architecture

    at least with matching size of GoInt.

    */

    typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];

     

    typedef struct { const char *p; GoInt n; } GoString;

    typedef void *GoMap;

    typedef void *GoChan;

    typedef struct { void *t; void *v; } GoInterface;

    typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

     

    #endif

     

    /* End of boilerplate cgo prologue. */

     

    #ifdef __cplusplus

    extern "C" {

    #endif

     

    extern GetLargeStruct_return* GetLargeStruct(GoInt p0);

     

    extern void FreeLargeStruct(GetLargeStruct_return* p0);

     

    /* Return type for GetLargeStruct2 */

    struct GetLargeStruct2_return {

      char* r0;

      GoInt r1;

    };

     

    extern struct GetLargeStruct2_return GetLargeStruct2(GoInt p0);

     

    extern void FreeCBytes(char* p0);

     

    #ifdef __cplusplus

    }

    #endif

     

     

     

    3.2 C++ 代码

    #include <Windows.h>

    #include <stdio.h>

    #include "sample3.h"

     

    typedef GetLargeStruct_return* (*funcPtrGetLargeStruct)(GoInt p0);

     

    typedef void (*funcPtrFreeLargeStruct)(GetLargeStruct_return* p0);

     

    typedef struct GetLargeStruct2_return (*funcPtrGetLargeStruct2)(GoInt p0);

     

    typedef void (*funcPtrFreeCBytes)(char* p0);

     

     

    int main(){

     

    HMODULE h = LoadLibraryA("sample3.dll");

    if (NULL == h || INVALID_HANDLE_VALUE == h)

    {

    return -1;

    }

     

    funcPtrGetLargeStruct pfGetLargeStruct = (funcPtrGetLargeStruct)GetProcAddress(h,"GetLargeStruct");

    funcPtrFreeLargeStruct pfFreeLargeStruct = (funcPtrFreeLargeStruct)GetProcAddress(h,"FreeLargeStruct");

     

     

    if (pfGetLargeStruct)

    {

    GetLargeStruct_return* result = pfGetLargeStruct(5);

    if (result)

    {

    printf("GetLargeStruct(5) return  %x %d\r\n",result->Data,result->DataLen);

    if (pfFreeLargeStruct)

    {

    pfFreeLargeStruct(result);

    }

    }

    }

     

     

     

     

    funcPtrGetLargeStruct2 pfGetLargeStruct2 = (funcPtrGetLargeStruct2)GetProcAddress(h,"GetLargeStruct2");

    funcPtrFreeCBytes pfFreeCBytes = (funcPtrFreeCBytes)GetProcAddress(h,"FreeCBytes");

     

     

    if (pfGetLargeStruct)

    {

    GetLargeStruct2_return result = pfGetLargeStruct2(5);

    printf("GetLargeStruct2(5) return  %x %d\r\n",result.r0,result.r1);

    if (pfFreeCBytes)

    {

    pfFreeCBytes(result.r0);

    }

    }

     

    FreeLibrary(h);

    return 0;

    }

     

    运行之后的输出:

     

     

     

    本文只讲述C/C++怎么调用golang程序,细节、注意事项及其他在后续随笔中介绍。

     

    参考文献:

     

    1. C? Go? Cgo!      https://blog.golang.org/c-go-cgo  
    2. Command cgo     https://golang.org/cmd/cgo/
    3. Cgo             https://github.com/golang/go/wiki/cgo
    4. cmd/cgo: Go type not supported in export: struct #18412

                      https://github.com/golang/go/issues/18412

     

    1. https://go.googlesource.com/go/+/master/src/cmd/cgo/doc.go

     

                       

     

    转载于:https://www.cnblogs.com/majianguo/p/7491508.html

    展开全文
  • C/C++调用Golang

    2017-09-06 20:33:00
    C/C++调用Golang 一 (开发环境: 操作系统: windows 7 32位操作系统 C++: visual studio 2010 Golang:go version go1.9 windows/386 TDM-GCC-32) 用一个简单的例子演示如何在C++中调用...

    C/C++调用Golang

     

     

    (开发环境:

    1. 操作系统: windows 7 32位操作系统  
    2. C++visual studio 2010   
    3. Golanggo version go1.9 windows/386   TDM-GCC-32

     

     

    用一个简单的例子演示如何在C++中调用golang程序。用golang编写一个简单的函数,编译成动态链接库,然后在C++中调用该go函数。

     

    第一阶段 Golang代码编译成动态链接库 (涉及2个文件 main.gogodll.def

     

    Golang : main.go  一个简单的Add函数

     

    package main

     

    import "C"

     

    //export Add

    func Add(a, b int32) int32 {

    return a + b

    }

     

    func main() {}

     

    为动态链接库指定导出符号,创建godll.def

    EXPORTS

        Add

     

     

     

     

     

     

     

     

    main.go编译成动态链接库,在命令行中执行如下操作:

    go build -buildmode=c-archive

     

     

    go build 生成了两个文件:godll.a godll.h

     

     

    执行  gcc -m32  -shared -o godll.dll godll.def godll.a -static -lwinmm -lWs2_32

     

    (需要安装  TDM-GCC-32)

     

    编译后生成 godll.dll

     

     

     

     

    godll.hgodll.dllC++工程需要的,godll.h的内容如下:

     

    /* Created by "go tool cgo" - DO NOT EDIT. */

     

    /* package _/Y_/godll */

     

    /* Start of preamble from import "C" comments.  */

     

     

     

     

    /* End of preamble from import "C" comments.  */

     

     

    /* Start of boilerplate cgo prologue.  */

    #line 1 "cgo-gcc-export-header-prolog"

     

    #ifndef GO_CGO_PROLOGUE_H

    #define GO_CGO_PROLOGUE_H

     

    typedef signed char GoInt8;

    typedef unsigned char GoUint8;

    typedef short GoInt16;

    typedef unsigned short GoUint16;

    typedef int GoInt32;

    typedef unsigned int GoUint32;

    typedef long long GoInt64;

    typedef unsigned long long GoUint64;

    typedef GoInt32 GoInt;

    typedef GoUint32 GoUint;

    typedef __SIZE_TYPE__ GoUintptr;

    typedef float GoFloat32;

    typedef double GoFloat64;

    typedef float _Complex GoComplex64;

    typedef double _Complex GoComplex128;

     

    /*

      static assertion to make sure the file is being used on architecture

      at least with matching size of GoInt.

    */

    typedef char _check_for_32_bit_pointer_matching_GoInt[sizeof(void*)==32/8 ? 1:-1];

     

    typedef struct { const char *p; GoInt n; } GoString;

    typedef void *GoMap;

    typedef void *GoChan;

    typedef struct { void *t; void *v; } GoInterface;

    typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

     

    #endif

     

    /* End of boilerplate cgo prologue.  */

     

    #ifdef __cplusplus

    extern "C" {

    #endif

     

     

    extern GoInt32 Add(GoInt32 p0, GoInt32 p1);

     

    #ifdef __cplusplus

    }

    #endif

     

     

    extern GoInt32 Add(GoInt32 p0, GoInt32 p1); 是导出函数的签名。

     

    depends22_x86 查看 godll.dll

     

     

     

     

    第二阶段  C++工程中调用godll.dll  

     

    创建名为callgovs 2010工程,将godll.h加入到工程,新建main.cpp的源文件:

     

    #include <Windows.h>

    #include <stdio.h>

    #include "godll.h"

     

    typedef GoInt32 (*funcPtrAdd)(GoInt32 p0, GoInt32 p1);

     

     

    int main(){

     

    HMODULE h = LoadLibraryA("godll.dll");

    if (NULL == h || INVALID_HANDLE_VALUE == h)

    {

    return -1;

    }

     

    funcPtrAdd pfAdd = (funcPtrAdd)GetProcAddress(h,"Add");

     

    if (pfAdd)

    {

    GoInt32 result = pfAdd(5,4);

    printf("Add(5,4) = %d",result);

    }

     

    FreeLibrary(h);

    return 0;

    }

     

     

    godll.h中的三行注释掉

    //typedef __SIZE_TYPE__ GoUintptr;

    typedef float GoFloat32;

    typedef double GoFloat64;

    //typedef float _Complex GoComplex64;

    //typedef double _Complex GoComplex128;

     

     

     

     

    编译运行,结果如下图:

     

     

     

    注意事项:

     

    main.go中  import "C" 这一行一定要有,否则gcc编译时会报符号未定义的错误:

     

    转载于:https://www.cnblogs.com/majianguo/p/7486812.html

    展开全文
  • <p>Now I have following golang code in my_go_call.go file. <pre><code>package main import "C" //export returnThis func returnThis(myString *C.char) *C.char { var result *C.char myStringGo := C.Go...
  • Python调用golang

    2020-09-29 16:06:30
    有些时候因为效率问题部分代码会 使用Python调用go的编译生成动态链接库 go 代码示例 //add.go package main import "C" //export Add func Add(a, b int) int { return a + b } //export Addstr func Addstr(a,...

    有些时候因为效率问题部分代码会 使用Python调用go的编译生成动态链接库

    go 代码示例

    //add.go
    package main
    
    import "C"
    
    //export Add
    func Add(a, b int) int {
    	return a + b
    }
    
    //export Addstr
    func Addstr(a, b *C.char) *C.char {
    	merge := C.GoString(a) + C.GoString(b)
    	return C.CString(merge)
    }
    
    // go build -buildmode=c-shared -o add.so add.go
    func main() {
    }
    
    

    注意 需要注意的是,这里的注释//export Addstr //export Add 不能省略,因为在编译成.so文件的时候,编译器会寻找这个注释。同时,为了能正常编译,我们也必须导入C这个包。

    ## 特別注意 //和export 中间不能有空格

    注意: 只有int可以不需要转换,直接在go和C直接互相调用
    对于不同的类型,需要使用cgo中定义的方法转换,具体可以参考golang-cgo文档。
    比如string需要用C.char来传递,C.GoString(s)可以将C.char类型转换为string,反之C.CString可以把string类型转为 *C.char
    Python是利用ctypes来跟so模块进行交互,其中存在着一个代码的翻译过程,包括数据类型的翻译,如果需要传参获取接收返回值,需要在golang中将参数按照下表对应,定义成C语言的数据类型。
    python,ctypes , c 对应类型参考 python 官方文档:https://docs.python.org/3.5/library/ctypes.html
    在这里插入图片描述

    把代码保存为fib.go,然后我们使用如下命令进行编译:

    go build -buildmode=c-shared -o add.so add.go
    

    这条命令指定了编译模式为c-shared,编译完成以后,当前文件夹下面会生成一个add.so文件。这就是我们需要用 Python 载入的文件了。
    注意: 不同平台下编译的add.so 不能通用,Windows下可以运行的so文件,linux下就不能运行,需要重新编译linux的so文件

    python 中调用go模块’

    # -*- coding:utf-8 -*-
    # @Time    : 2020/9/29
    # @Author  : hllyzms
    import ctypes
    
    lib = ctypes.cdll.LoadLibrary('./add.so')
    
    result = lib.Add(2020, 1)
    print(result)
    
    add = lib.Addstr  #调用go模块
    # 显式声明参数和返回的期望类型
    add.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
    add.restype = ctypes.c_char_p
    str1 = add("abc".encode("utf-8"),'efg'.encode("utf-8"))
    print(str1,type(str1))
    
    

    结果:

    2021
    b'abcefg' <class 'bytes'>
    

    注意 Addstr 传入测参数要转换成byte类型

    go中的*C.char 对应 ctypes 中的c_char_p 对应Python中的bytes object or None

    Python与Go之间的参数传递, 处理非INT型时需要都转为对应的C类型
    ctypes需要显式地声明DLL函数的参数和返回期望的数据类型
    注意在Python3中字符串bytes和string的区别
    Go模块需要//export 声明外部可调用
    Go处理C的类型是需要显式转换

    展开全文
  • GOlang 静态库文件和头文件复制到C文件夹下 执行GCC 命令 >gcc -v test.c -o test1 main.a demo.so -lWinMM -lntdll -lWS2_32 运行test1 转载于:...
  • <p>I've "hello world" rpc service written on golang. It works fine and go jsonrpc client is working. But I need to send request with curl and this example doesn't work: <pre><code>curl \ -X POST \ -H...
  • electron/nodejs实现调用golang函数

    千次阅读 2019-09-26 08:39:52
    https://www.jianshu.com/p/a3be0d206d4c 思路 ... c++可以调用动态链接库,所以基本思路是golang开发主要功能, c++开发插件包装golang函数,实现中转调用 对于类型问题, 为了方便处理, 暴露的gola...
  • Anyone know a way to call golang functions from Tcl script? <pre><code>static int create_utility_tcl_cmds(Tcl_Interp* interp) { if (Tcl_CreateObjCommand(interp, "ip_v4_address", ip_address, ...
  • main.go package main import ( "C" "bytes" "fmt" "io/ioutil" ... "golang.org/x/text/encoding/...func cstr(s *C.char) *C.char { gostr := C.GoString(s) fmt.Println("go:" + gostr) return C
  • 写自定义包的源文件 注意路径!注意路径!注意路径!重要的事情说三遍! 这个文件夹及其源代码... C string } 调用自定义包 在main.go中代码如下: package main import ( fmt ./pack1 ) func main() { struct1 :=
  • <p>Here is the golang source that I've built to c-style lib : <pre><code>package main import "C" import ( "bufio" "fmt" "log" "os" ) func main() {} //export ReadSomething func ReadSomething...
  • <pre><code>package main import "fmt" import "reflect" type T struct{} ... 0x0, 0x0, 0xc420049f00, 0x0, 0x0, 0x0, 0x0, 0x40457c) /usr/local/go/src/reflect/value.go:300 +0x38 </div>
  • 我们知道,在涉及到大量 CPU...并且,我们这次不是做转换,而是直接用 Python 调用 Go 语言写的代码。 今天的文章内容需要使用 Linux 和 macOS 系统实现。或者你也可以使用 Windows 10自带的 WSL2 Linux子系统。 今天我
  • golang调用C

    千次阅读 2016-03-09 14:47:59
    golang调用C
  • <p>Can Go functions be called by <code>C++</code> or <code>C#</code> code on windows? Does Go support generating dll in Windows? </div>
  • golang 调用C,C++

    2020-09-27 18:05:51
    前言:Golang调用是通过cgo完成的,Golang调用C++,则需要将C++函数导出包装为C函数,然后再通过cgo完成调用,话不多说,直接给出调用示例。 开发工具:Clion,Goland 首先msys2,通过msys2安装mingw,cmake等开发C...
  • golang调用c文件

    千次阅读 2018-06-08 17:33:54
    c语言的头文件foo.h int count; void foo(); c语言的实现文件foo.c #include &lt;stdio.h&gt; #include "foo.h"...golang调用c语言 package main // #include &l...
  • 参考文档: JNA的官方文档:http://java-native-access.github.io/jna/5.5.0/javadoc/ JNA的github:... github的一个case:Calling Go Functions from Other Languages using C Shared Lib...
  • Golang调用C

    千次阅读 2013-12-29 22:27:51
    Golang调用C  2010-04-18 13:21:28| 分类: 积累 | 标签: |字号大中小 订阅 Golang调用C分两个步骤:1 写一个C的wrapper,这个很简单;2 对wrapper做编译,这个步骤有点复杂,而且涉及众多中间文件。应该...
  • golangC互相调用示例

    千次阅读 2019-04-21 18:49:06
    以下示例使用的操作系统都是...一、c语言调用golang库 1.main.go package main import "C" func main() {} //export Hello func Hello() string { return "Hello" } //export Test func Test() { pr...
  • golang 调用c代码

    2020-08-27 15:47:03
    首先先上代码,看看效果。...import "C" func main(){ C.sayHello() } 如果在执行时报错exec: "gcc": executable file not found in %PATH%,可以查看executable file not found in %PATH%的解决。
  • <p>Can I write a C++ client to call a GRPC routing written in golang? If possible does it need some kind of redirection, i.e, via a stub in C++ invoking golang function? or Is GRPC agnostic what ...
  • SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。 最新的版本已经开始支持...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 547
精华内容 218
关键字:

c调用golang