英文:
Go Exception "signal arrived during cgo execution"
问题
在调用dll时,Go会在什么情况下出现类似"在cgo执行期间收到信号"的panic?
要调用的代码是基于Go发行版中src
目录下的zsyscall_windows.go
中的示例:
var (
// 使用dumpbin /exports找到的入口名称
dllSweph = syscall.NewLazyDLL("swedll32.dll")
_swe_jdut1_to_utc = dllSweph.NewProc("_swe_jdut1_to_utc@36")
_swe_julday = dllSweph.NewProc("_swe_julday@24")
)
func swe_julday(year, month, day int32, hour float64, gregflag int32) float64 {
r, _, errn := syscall.Syscall6(
_swe_julday.Addr(),
5,
uintptr(year),
uintptr(month),
uintptr(day),
uintptr(hour),
uintptr(gregflag),
0)
if r == 0 {
if errn != 0 {
panic(error(errn))
}
}
return float64(r)
}
func swe_jdut1_to_utc(tjd_ut float64, gregflag int32, iyear, imonth, iday, ihour, imin *int32, dsec *float64) {
defer func() {
if e := recover(); e != nil {
}
}()
syscall.Syscall9(
_swe_jdut1_to_utc.Addr(),
8,
uintptr(tjd_ut),
uintptr(gregflag),
uintptr(unsafe.Pointer(iyear)),
uintptr(unsafe.Pointer(imonth)),
uintptr(unsafe.Pointer(iday)),
uintptr(unsafe.Pointer(ihour)),
uintptr(unsafe.Pointer(imin)),
uintptr(unsafe.Pointer(dsec)),
0)
}
现在当我调用swe_julday
时,一切似乎都很正常,尽管实际上并不是这样,它给出了一个错误的答案。而当调用swe_jdut1_to_utc
时,我得到了以下错误:
Exception 0xc0000005 0x1 0x42e5e5 0x3235ce40
PC=0x3235ce40
signal arrived during cgo execution
.../sweph.swe_jdut1_to_utc(0x40000000, 0x4150b979, 0x1, 0x1207bf24, 0x1207bf28, 0x1207bf34, 0x1207bf30, 0x1207bf2c, 0x1207bf38)
...(trace info)
eax 0x0
ebx 0x1207be94
ecx 0x1207bf38
edx 0x42e5e5
edi 0xcfeac
esi 0x0
ebp 0xcfe5c
esp 0xcfdd8
eip 0x3235ce40
eflags 0x10246
cs 0x23
fs 0x53
gs 0x2b
exit status 2
exit status 1
环境:
- Windows 8 x64
- Go 1.4 x86
- GCC x86
我不知道是否真的需要gcc
来调用一个dll,但我已经安装了它,因为错误是关于cgo
的。所有命令都在路径中。使用管理员权限编译时出现相同的错误。
被调用的C
函数是:
void swe_jdut1_to_utc (double tjd_ut, int32 gregflag, int32 *iyear, int32 *imonth, int32 *iday, int32 *ihour, int32 *imin, double *dsec)
而在该dll中导入并调用此函数的C#
函数是:
[DllImport("swedll32.dll", EntryPoint = "swe_jdut1_to_utc")]
public static extern void swe_jdut1_to_utc(
double tjd_ut,
int gregflag,
ref Int32 iyear, ref Int32 imonth, ref Int32 iday,
ref Int32 ihour, ref Int32 imin, ref double dsec);
英文:
In what circumstances Go panics like "signal arrived during cgo execution" when calling a dll?
The code to be called is - based on samples in zsyscall_windows.go
in src
of go distribution:
var (
// entry names found using dumpbin /exports
dllSweph = syscall.NewLazyDLL("swedll32.dll")
_swe_jdut1_to_utc = dllSweph.NewProc("_swe_jdut1_to_utc@36")
_swe_julday = dllSweph.NewProc("_swe_julday@24")
)
func swe_julday(year, month, day int32, hour float64, gregflag int32) float64 {
r, _, errn := syscall.Syscall6(
_swe_julday.Addr(),
5,
uintptr(year),
uintptr(month),
uintptr(day),
uintptr(hour),
uintptr(gregflag),
0)
if r == 0 {
if errn != 0 {
panic(error(errn))
}
}
return float64(r)
}
func swe_jdut1_to_utc(tjd_ut float64, gregflag int32, iyear, imonth, iday, ihour, imin *int32, dsec *float64) {
defer func() {
if e := recover(); e != nil {
}
}()
syscall.Syscall9(
_swe_jdut1_to_utc.Addr(),
8,
uintptr(tjd_ut),
uintptr(gregflag),
uintptr(unsafe.Pointer(iyear)),
uintptr(unsafe.Pointer(imonth)),
uintptr(unsafe.Pointer(iday)),
uintptr(unsafe.Pointer(ihour)),
uintptr(unsafe.Pointer(imin)),
uintptr(unsafe.Pointer(dsec)),
0)
}
Now when I call swe_julday
everything seems to be fine; although it's not and it gives a wrong answer. And when swe_jdut1_to_utc
is called, I get:
Exception 0xc0000005 0x1 0x42e5e5 0x3235ce40
PC=0x3235ce40
signal arrived during cgo execution
.../sweph.swe_jdut1_to_utc(0x40000000, 0x4150b979, 0x1, 0x1207bf24, 0x1207bf28, 0x1207bf34, 0x1207bf30, 0x1207bf2c, 0x1207bf38)
...(trace info)
eax 0x0
ebx 0x1207be94
ecx 0x1207bf38
edx 0x42e5e5
edi 0xcfeac
esi 0x0
ebp 0xcfe5c
esp 0xcfdd8
eip 0x3235ce40
eflags 0x10246
cs 0x23
fs 0x53
gs 0x2b
exit status 2
exit status 1
Environment:
Windows 8 x64
go 1.4 x86
gcc x86
And I do not know if gcc
is really needed to just call a dll, but I've installed it any way because the error was about cgo
. All commands are in the path. Same error when compiling with administrative privileges.
The C
function that is being called is:
void swe_jdut1_to_utc (double tjd_ut, int32 gregflag, int32 *iyear, int32 *imonth, int32 *iday, int32 *ihour, int32 *imin, double *dsec)
And the C#
function which imports and calls this function in that dll (& works) is:
[DllImport("swedll32.dll", EntryPoint = "swe_jdut1_to_utc")]
public static extern void swe_jdut1_to_utc(
double tjd_ut,
int gregflag,
ref Int32 iyear, ref Int32 imonth, ref Int32 iday,
ref Int32 ihour, ref Int32 imin, ref double dsec);
答案1
得分: 1
我成功构建了一个使用swe_julday函数的Delphi应用程序。不幸的是,我发现它使用fstp汇编指令来获取swe_julday返回的结果。Go的syscall.Syscall不支持这个功能。很抱歉,你运气不好。我认为你最好的选择是如果可能的话,使用CGO来使用mingw编译器构建你的库。抱歉。
英文:
I managed to build delphi app that uses swe_julday function. Unfortunately I can see it uses fstp asm instruction to retrieve result returned by swe_julday. Go's syscall.Syscall does not support this functionality. You are our of luck. I think your best bet is to use CGO if it is possible to build your library with mingw compiler. Sorry
Alex
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论