#c #go #dll
#c #Вперед #dll
Вопрос:
Я работаю с go и dll, и мне нужно создать go dll, которая экспортирует функцию, которая принимает структуру go.
//test.go
package main
import "fmt"
//export TestFunc
func TestFunc(s TestStruct) {
fmt.Println(s.a)
}
func main() {}
//teststruct.go
package main
type TestStruct struct {
a int
}
и строить с
go build -buildmode=c-shared -o test.dll .test.go .teststruct.go
Я получаю идеальный DLL-файл.
Теперь, когда я использую этот код Go для его вызова
//testcall.go
package main
import (
"log"
"syscall"
"unsafe"
)
func main() {
l, e := syscall.LoadLibrary("test.dll")
if e != nil {
log.Fatal(e)
}
p, e := syscall.GetProcAddress(l, "TestFunc")
if e != nil {
log.Fatal(e)
}
_, _, _ = syscall.Syscall(p, 1, uintptr(unsafe.Pointer(amp;TestStruct{
a: 1002,
})), 0, 0)
}
и запустить с
go run .testcall.go .teststruct.go
Я получаю фатальную ошибку:
Не удалось найти указанную процедуру.
Когда я делаю то же самое на C, это работает нормально:
//test.c
#include <stdio.h>
#include "struct.h"
__declspec(dllexport) void TestFunc(struct TestStruct s) {
printf("%dn", s.a);
}
//testcall.c
#include <windows.h>
#include "struct.h"
int main() {
HINSTANCE l = LoadLibrary("test.dll");
FARPROC p = GetProcAddress(l, "TestFunc");
struct TestStruct s;
s.a = 1002;
p(s);
}
//teststruct.h
struct TestStruct {
int a;
};
и строить с:
gcc -c test.c
gcc -shared -o test.dll test.o
gcc .testcall.c
Я не получаю никаких ошибок, и это дает мне
1002
Кроме того, если я использую import "C"
в своем файле test.go, это даст мне
нераспознанный тип Go TestStruct
и это должно произойти, потому что C не знает, что это за тип. Итак, есть ли какой-либо способ использовать структуру go в качестве параметра и почему это выдает мне procedure not found
ошибку?
Комментарии:
1. Какой оператор завершается ошибкой? Также обратите внимание, что ваша функция принимает свой аргумент по значению, но при вызове вы передаете указатель.
2.
syscall.GetProcAddress
сбой. (Я поставил фиктивный оператор печати для проверки)3. Я также тестировал, принимая a
*TestStruct
вместоTestStruct
параметра, но это также не удается.4. Вы не импортируете «C», поэтому он не создает экспорт. Вы не можете экспортировать тип Go, потому что интерфейс — это C, а не Go.
5. Единственный способ взаимодействовать с общим объектом — через его C api, поэтому в этом контексте нет такого понятия, как «тип go».