调用纯class="superseo">c,可以直接把代码嵌入go,
如果是c++,笔者没有找到直接嵌入go的好方法
笔者找到可行的方法是,
把c++代码编译成动态库,
再做一个纯c接口,调用相应的c++代码
对象(不管是struct还是class)统一用void* 代替,并提供接口设置对象的成员变量
库文件一定要以 libxxx.so libxxx.dll这个的方式命名(go是linux style)
示例代码如下(以vsstudio为例,linux下面对应直接make生成.so即可)
c++ dll代码
如果是用vsstudio dll导出要用.def的方式进行,如下
LIBRARY libtestdll
EXPORTS
TestDLLAdd
TestDLLSub
如果是linux,对应的生成.so makefile
INCL=-I./include
LIBDIR=-L./lib
LIB=
OUTPUT=./
FLAG=-fPIC
.SUFFIXES: .cpp .c
.cpp.o:
g++ ${INCL} ${FLAG} -c $<
.c.o:
gcc $(INCL) ${FLAG} -c $<
all: clean libtest.so test
libtest.so: testdll.o testcpp.o
gcc -o $@ -shared $? $(LIBDIR) $(LIB) -lstdc++
mv ./libtest.so ./lib/
test: main.o
gcc -o $@ $? $(LIBDIR)$(LIB) -ltest
clean:
rm -fr ./*.o
linux动态库路径设置 LD_LIBRARY_PATH, 笔者就直接在 /root/.bashrc里设置,设置完记得source一下才能生效
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/lsc/go/cppdll/lib
c++代码
// 头文件
#pragma once
class TestCpp
{
public:
TestCpp();
~TestCpp();
void SayHello();
};
// cpp文件
#include "testcpp.h"
#include
TestCpp::TestCpp()
{
printf("i born\r\n");
}
TestCpp::~TestCpp()
{
printf("see you\r\n");
}
void TestCpp::SayHello()
{
printf("hello \r\n");
}
再用纯c封装一下
头文件:
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C" {
#endif
int TestDLLAdd(int a, int b);
int TestDLLSub(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
cpp文件
#include "testdll.h"
#include "testcpp.h"
int TestDLLAdd(int a, int b)
{
TestCpp tc;
tc.SayHello();
return a + b;
}
int TestDLLSub(int a, int b)
{
return a - b;
}
在go代码中调用
如下
/*
#cgo CFLAGS: -Icpp
#cgo LDFLAGS: -Llib -ltestdll
#include "testdll.h"
*/
import "C"
func main() {
fmt.Println(C.TestDLLAdd(41,22))
}
其中 -Icpp 表示.h文件所在目录是./cpp
-Llib表示对应的 libxxx.lib libxxx.dll所在的目录是 ./lib
-ltestdll:表示动态库的名字, 生成的是啥,就写啥 一定要命名成 libxxx.so 或者 libxxx.dll
运行之后就会是这样
参数类型
如果整形 C.int
如果是size_t对应的go类型是 C.size_t
如果是字符串指针 对应的是 *C.char
以此类推,所有的c内置类型对应的go类型都加上 C.就可以,
考虑到字节对齐问题,尽量避免使用结构体做参数
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)