猿问

从 Go 应用程序中的线程低级 C/C++ 代码层调用 Go 回调

我有一个 Go 应用程序和一些 C API 函数(例如一些 Win32 API 函数),它们异步工作并产生工作线程。此 API 函数从其中一些工作线程调用回调。线程是系统线程,由 C 代码(而不是 Go)在内部创建。现在,我想将 Go 函数作为回调传递给该 C API 函数。因此,Go 回调函数将由 C 函数在工作线程的上下文中调用,Go 应用程序不知道。

我们可以假设已经采取了安全措施,并且回调中的所有数据访问都由互斥锁适当地保护,以免干扰主 Go 代码。

问题是“Go 是否支持这种情况?”,即回调会正常工作还是因为 Go 运行时不是为我想做的事情而设计的东西很容易在内部崩溃?


慕后森
浏览 109回答 1
1回答

BIG阳

我进行了一个 Go 回调的实验,从 20 个本地 Windows 线程并行调用。回调增加一个变量,将元素添加到地图并在屏幕上打印值。一切都很顺利,所以我认为在更复杂的场景中也不会出现问题。这是我的测试的源代码供其他人使用:代理.h#ifndef _PROXY_H_#define _PROXY_H_long threaded_c_func(long param);#endif代理.c#include "proxy.h"#ifdef WIN32#include <Windows.h>#endif#define ROUNDS 20volatile long passed = 0;extern long long threadedCallback(long cbidx);DWORD WINAPI ThreadFunc(LPVOID param) {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; threadedCallback(*((long *)param));&nbsp; &nbsp; InterlockedIncrement(&passed);}long threaded_c_func(long cbidx) {&nbsp; &nbsp; for (int i&nbsp; = 0; i < ROUNDS; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; DWORD ThreadId = 0;&nbsp; &nbsp; &nbsp; &nbsp; CreateThread(NULL, 1024*1024, &ThreadFunc, (LPVOID) &cbidx, 0, &ThreadId);&nbsp; &nbsp; }&nbsp; &nbsp; while (passed < ROUNDS)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Sleep(100);&nbsp; &nbsp; }&nbsp; &nbsp; return ROUNDS;}&nbsp;回调Test.gopackage main/*#cgo CFLAGS: -I .#cgo LDFLAGS: -L .#include "proxy.h"long threaded_c_func(long param);*/import "C"import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "strconv"&nbsp; &nbsp; "sync")var hashTable map[int32]stringvar count int32var mtx sync.Mutex//export threadedCallbackfunc threadedCallback(cbidx int) C.longlong {&nbsp; &nbsp; mtx.Lock()&nbsp; &nbsp; defer mtx.Unlock()&nbsp; &nbsp; count++&nbsp; &nbsp; hashTable[count] = strconv.Itoa(int(count))&nbsp; &nbsp; fmt.Println("Current counter ", count)&nbsp; &nbsp; return C.longlong(count)}func main() {&nbsp; &nbsp; hashTable = make(map[int32]string)&nbsp; &nbsp; var expected C.long&nbsp; &nbsp; expected = C.threaded_c_func(1)&nbsp; &nbsp; if int32(expected) == count {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Counters match")&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Expected ", int32(expected), " got ", count)&nbsp; &nbsp; }&nbsp; &nbsp; for k, v := range hashTable {&nbsp; &nbsp; &nbsp; &nbsp; if strconv.Itoa(int(k)) == v {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(v, " match")&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(v, "don't&nbsp; match")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Go
我要回答