I have a test code that has this stack C#->C->GO->C#(ERROR HERE).
Whenever an error happens on C# and if that C# code is called by GOLANG the error is not redirected to error.std file. However, if I start the code from VS with the attached debugger the error is redirected to the file.
C#: Program.cs
class Program {
[DllImport("gotestDLL.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern void Error();
[DllImport("gotestDLL.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern void SetCSharpPointerHandler(IntPtr ptr);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr CSharpPointerHandler(IntPtr message);
private static CSharpPointerHandler _messageHandlerCb = new CSharpPointerHandler(SomeMethodWithError);
private static IntPtr _messageHandlerCbPtr = Marshal.GetFunctionPointerForDelegate(_messageHandlerCb);
static void Main(string[] args) {
SetCSharpPointerHandler(_messageHandlerCbPtr);
Console.WriteLine("|-C#->START OF C#");
Error();
Console.WriteLine("|-C#->Waiting for program to crash");
do {
} while (true);
}
private static IntPtr SomeMethodWithError(IntPtr messagePtr) {
Console.WriteLine("|-C#->Back to C#");
var a = 0;
Console.WriteLine("|-C#->ERROR HAPPENS HERE C#");
var b = 10 / a;
Console.WriteLine(b);
return IntPtr.Zero;
}
}
C:ctestdll.C
#include <stdio.h>
#include "gotestDLL.h"
void Error() {
printf("|-C--->START OF C\n");
RedirectStdError();
printf("|-C--->START ERROR\n");
StartError();
printf("|-C--->END START ERROR\n");
printf("|-C-->END OF C\n");
}
int main() {
}
H:ctestDLL.h
#include <stdio.h>
#include <stdbool.h>
typedef char* CSharpPointerHandler(char* query);
static inline char* RunCSharpPointerHandler(CSharpPointerHandler* handler, char* in) {
return handler(in);
}
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void SetCSharpPointerHandler(CSharpPointerHandler* handler);
__declspec(dllexport) void Error();
#ifdef __cplusplus
}
#endif
GO:gotestDLL.go
package main
/*
#include<stdio.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include "ctestDLL.h"
*/
import "C"
import "fmt"
import "os"
var queryHandler *C.CSharpPointerHandler = nil
//export SetCSharpPointerHandler
func SetCSharpPointerHandler(handler *C.CSharpPointerHandler) {
queryHandler = handler
}
//export StartError
func StartError() {
inc := C.CString("TEST")
fmt.Println("|-GO--->Calling Handler from GO->C#")
C.RunCSharpPointerHandler(queryHandler, inc)
fmt.Println("|-GO--->END Calling Handler from GO")
}
//export RedirectStdError
func RedirectStdError() {
f, err := os.OpenFile("error.std", os.O_WRONLY | os.O_CREATE | os.O_SYNC, 0777)
if err != nil {
fmt.Println("os.OpenFile")
}
newfd := C._open_osfhandle(C.intptr_t(f.Fd()), C._O_APPEND | C._O_TEXT)
if newfd == C.int(-1) {
fmt.Println("failed to create osfhandle: _open_osfhandle(%v, _O_APPEND|_O_TEXT)", C.intptr_t(f.Fd()))
}
stderr_fd := C._fileno(C.stderr)
forwarded := C._dup2(newfd, stderr_fd)
if forwarded == C.int(-1) {
fmt.Println("failed to duplicate stderr fd: _dup2(%v, %v): %v", newfd, stderr_fd, forwarded)
}
os.Stderr = f
}
func main() {
// Need a main function to make CGO compile package as C shared library
}
OUTPUT:
|-C#->START OF C#
|-C--->START OF C
|-C--->START ERROR
|-GO--->Calling Handler from GO->C#
|-C#->Back to C#
|-C#->ERROR HAPPENS HERE C#