有没有一种方法可以从Microsoft Visual Studio C++中调用go代码?

vc6uscn9  于 2023-08-01  发布在  Go
关注(0)|答案(1)|浏览(129)

有没有一种方法可以从Microsoft Visual Studio C中调用go代码?
请不要随意关闭我的问题。
这个链接How to build a library with cgo using visual studio compiler?没有回答我的问题。它没有给予一个可行的解决方案。
目前看来cgo只能用mingw gcc编译。https://github.com/golang/go/issues/49080#issuecomment-947865866
所以,这个问题目前看来是无法解决的。
由于mingw c头文件与Windows SDK不完全相同,因此总会有一些代码无法工作。
这就像是一个“是”还是“不是”的问题。
如果你想从c
调用go代码,使用mingw gcc编译你所有的代码。
你不能用mingw编译cgo,然后在Visual Stdudio C中使用它。(也许它会工作,但总会有一些代码不工作)
我所能找到的就是用mingw gcc编译cgo,就像这个链接https://gist.github.com/geraldstanje/4624ac47eb3dec5b8bbe12d4714ed330
但这种方法有一个问题。
如果将.a库与普通的visual c
代码链接,则会失败,因为.a库包含visual c++不知道的符号

clang -w *.cpp v2pn.a
LINK : warning LNK4217: symbol '__acrt_iob_func' defined in 'libucrt.lib(_file.obj)' is imported by 'v2pn.a(000005.o)' in function '_cgo_preinit_init'
LINK : warning LNK4286: symbol '__acrt_iob_func' defined in 'libucrt.lib(_file.obj)' is imported by 'v2pn.a(000006.o)'
LINK : warning LNK4217: symbol '_errno' defined in 'libucrt.lib(errno.obj)' is imported by 'v2pn.a(000005.o)' in function '_cgo_beginthread'
v2pn.a(000005.o) : error LNK2019: unresolved external symbol __imp__beginthread referenced in function _cgo_beginthread
v2pn.a(000005.o) : error LNK2019: unresolved external symbol __mingw_vfprintf referenced in function fprintf
v2pn.a(000006.o) : error LNK2001: unresolved external symbol __mingw_vfprintf
a.exe : fatal error LNK1120: 2 unresolved externals
clang: error: linker command failed with exit code 1120 (use -v to see invocation)

字符串
如果用mingw gcc链接带有visual c++代码的.a库
会有更多的问题。由于mingw头文件与Windows SDK头文件不完全同步,因此会出现很多错误。
就像这个

gcc.exe *.cpp v2pn.a
v2pn.cpp: In function 'void set_dns_by_guid(PCHAR)':
v2pn.cpp:48:5: error: 'DNS_INTERFACE_SETTINGS' was not declared in this scope
   48 |     DNS_INTERFACE_SETTINGS settings = {DNS_INTERFACE_SETTINGS_VERSION1};
      |     ^~~~~~~~~~~~~~~~~~~~~~
v2pn.cpp:49:5: error: 'settings' was not declared in this scope
   49 |     settings.Flags = 0x0002;
      |     ^~~~~~~~
v2pn.cpp:51:17: error: 'SetInterfaceDnsSettings' was not declared in this scope
   51 |     DWORD ret = SetInterfaceDnsSettings(interfaceGUID, &settings);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~


这是因为mingw netioapi. h头文件与Windows SDK netioapi. h不同。
Windows SDK netioapi. h头文件包含DNS_INTERFACE_SETTINGS声明,但mingw netioapi. h头文件不包含。

e37o9pze

e37o9pze1#

就像你说的,cgo不支持链接MSVC C库。即使你尝试公开纯C类API并尝试链接,你也很可能会陷入名称混乱的问题。一个可行的解决方案是围绕需要公开的C API编写一个C Package 器,并使用适当的外部前缀。这将使您摆脱C++名称混乱的问题,并且cgo不会区分C库是从哪个编译器编译的。
例如,API.cpp

class CppApi {
  int Run(int arg1);
}

字符串
CAPI.h

#ifdef API_EXPORTS
#define RUN_API __declspec(dllexport)
#else
#define RUN_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
  RUN_API void* GetAPI();
  RUN_API int Run(void* obj, int arg1);
#ifdef __cplusplus
}
#endif


CAPI.cpp

void* GetAPI() {
  return (void*)(new CppApi());
}
int Run(void* obj, int arg1) {
  CppApi cppObj = CppApi*)obj;
  return cppObj->Run(arg1);
}


请注意,只有当您愿意公开纯C函数而不使用任何C++类型或任何Microsoft类型时,此解决方案才有效。

相关问题