1

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#
Jonathan
  • 19
  • 3

0 Answers0