英文:
How to remove "extern" functions in C and be able to use them from golang?
问题
我有一个C++库的C包装器,我想在golang中使用它。我想要的回调路径是golang->C->C++。我已经测试了C->C++部分,但在golang->C部分遇到了困难。
根据维基百科上的说法,我尝试了这个示例(https://github.com/golang/go/wiki/cgo#function-variables)。在Linux上运行良好,但在Windows上编译时失败,因为我将C库和golang分开编译。
我认为可以将C库分成完全不了解golang的部分,并将带有"extern"关键字的回调放入golang目录。但我认为这对我来说不合适,因为我需要的函数看起来像这样:
ClipperPaths64 *
clipper_clipperoffset_execute_gocallback(void *mem, ClipperClipperOffset *c, uintptr_t h) {
auto result = new (mem) Paths64();
from_c(c)->Execute(from_c(h), *result);
return to_c(result);
}
你看到我使用了from_c(...)
函数,它们返回C++对象,它们没有公开在这个库中,我不能使用它们。
如果有帮助的话,我可以分享更多的代码。
英文:
I have a C wrapper of C++ library that I want to use with golang. Overall path of callback that I want is golang->C->C++. I tested part C->C++, but face difficulties with golang->C part.
As said in wiki, I tried this example. It works good on linux, but when I compile it on windows it fails on "extern" keyword because I compile C library and golang separately.
I thought that it is possible to split C library on part that doesn't know about golang at all. And put this callback with "extern" keyword into golang directory. But I think this will not fit me because function that takes callback and I need looks like this:
ClipperPaths64 *
clipper_clipperoffset_execute_gocallback(void *mem, ClipperClipperOffset *c, uintptr_t h) {
auto result = new (mem) Paths64();
from_c(c)->Execute(from_c(h), *result);
return to_c(result);
}
You see that I use from_c(...)
functions and they return C++ objects, they are not exposed publicly of this library and I cannot use them.
I would share more code if it would be helpful.
答案1
得分: 0
好的,以下是翻译好的内容:
解决方案:
只需将“extern”函数移动到golang模块的目录中。您将单独编译C/C++库,并将回调函数和在golang文件中定义的任何内容放置在与golang代码相邻的位置。
callback.c示例:
// 定义delta回调函数
double delta_callback(
uintptr_t h,
ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx)
{
return goDeltaCallback64(h, path, path_normals, curr_idx, prev_idx);
}
callback.h:
#ifndef CLIBRARY_H
#define CLIBRARY_H
#include <stddef.h>
#include "../lib/clipper2c/clipper2c.h"
typedef double (*callbackfunc) (
uintptr_t h, ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx);
double delta_callback(
uintptr_t h,
ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx);
extern double goDeltaCallback64(uintptr_t h, ClipperPath64 *path,
ClipperPathD *path_normals, size_t curr_idx,
size_t prev_idx);
#endif
.go文件:
//export goDeltaCallback64
func goDeltaCallback64(
h C.uintptr_t,
path *C.ClipperPath64,
path_normals *C.ClipperPathD,
curr_idx C.size_t,
prev_idx C.size_t,
) C.double {
fn := cgo.Handle(h).Value().(ClipperOffsetCallback)
gopath := &Path64{
p: path,
}
gopath_normals := &PathD{
p: path_normals,
}
return C.double(fn(gopath, gopath_normals, int(curr_idx), int(prev_idx)))
}
英文:
Well, it is solved and as reference you may peek my repo: here
Solution:
Just move function that is "extern" to directory of golang module. You will compile separately C/C++ library and alongside golang code you can place callbacks and whatever you will define in golang file.
Example of callback.c:
// define delta callback
double delta_callback(
uintptr_t h,
ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx)
{
return goDeltaCallback64(h, path, path_normals, curr_idx, prev_idx);
}
callback.h:
#ifndef CLIBRARY_H
#define CLIBRARY_H
#include <stddef.h>
#include "../lib/clipper2c/clipper2c.h"
typedef double (*callbackfunc) (
uintptr_t h, ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx);
double delta_callback(
uintptr_t h,
ClipperPath64 *path, ClipperPathD *path_normals,
size_t curr_idx, size_t prev_idx);
extern double goDeltaCallback64(uintptr_t h, ClipperPath64 *path,
ClipperPathD *path_normals, size_t curr_idx,
size_t prev_idx);
#endif
.go:
//export goDeltaCallback64
func goDeltaCallback64(
h C.uintptr_t,
path *C.ClipperPath64,
path_normals *C.ClipperPathD,
curr_idx C.size_t,
prev_idx C.size_t,
) C.double {
fn := cgo.Handle(h).Value().(ClipperOffsetCallback)
gopath := &Path64{
p: path,
}
gopath_normals := &PathD{
p: path_normals,
}
return C.double(fn(gopath, gopath_normals, int(curr_idx), int(prev_idx)))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论