go-python / gopy

gopy generates a CPython extension module from a go package.
BSD 3-Clause "New" or "Revised" License
2.05k stars 113 forks source link

Imported types not working properly #303

Open matthews34 opened 1 year ago

matthews34 commented 1 year ago

I'm trying to build a function which uses imported types as argument and as return type:

package request

import "github.com/Danny-Dasilva/CycleTLS/cycletls"

func Request(method string, url string, options cycletls.Options) (cycletls.Response, error) {
    client := cycletls.Init()

    response, err := client.Do(url, options, method)

    return Response(response), err
}

However, the python types are not being generated properly, so I get the following error when trying to pass a cycletls.Options to the Request function in python:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7f5523f2a520]

goroutine 17 [running, locked to thread]:
main.request_Request(0xc00003e060?, 0x0?, 0x1?)
        /home/matheus/tests/go-request/request/request.go:1881 +0xe0
Aborted

Here are the go types:

type Options struct {
    URL             string            `json:"url"`
    Method          string            `json:"method"`
    Headers         map[string]string `json:"headers"`
    Body            string            `json:"body"`
    Ja3             string            `json:"ja3"`
    UserAgent       string            `json:"userAgent"`
    Proxy           string            `json:"proxy"`
    Cookies         []Cookie          `json:"cookies"`
    Timeout         int               `json:"timeout"`
    DisableRedirect bool              `json:"disableRedirect"`
    HeaderOrder     []string          `json:"headerOrder"`
    OrderAsProvided bool              `json:"orderAsProvided"`
}

type Response struct {
    RequestID string
    Status    int
    Body      string
    Headers   map[string]string
}

And here are the generated python types:

# Python type for cycletls.Options
class cycletls_Options(GoClass):
    """"""
    def __init__(self, *args, **kwargs):
        """
        handle=A Go-side object is always initialized with an explicit handle=arg
        """
        if len(kwargs) == 1 and 'handle' in kwargs:
            self.handle = kwargs['handle']
            _request.IncRef(self.handle)
        elif len(args) == 1 and isinstance(args[0], GoClass):
            self.handle = args[0].handle
            _request.IncRef(self.handle)
        elif len(args) == 1 and isinstance(args[0], int):
            self.handle = args[0]
            _request.IncRef(self.handle)
        else:
            self.handle = 0
    def __del__(self):
        _request.DecRef(self.handle)

# Python type for cycletls.Response
class cycletls_Response(GoClass):
    """"""
    def __init__(self, *args, **kwargs):
        """
        handle=A Go-side object is always initialized with an explicit handle=arg
        """
        if len(kwargs) == 1 and 'handle' in kwargs:
            self.handle = kwargs['handle']
            _request.IncRef(self.handle)
        elif len(args) == 1 and isinstance(args[0], GoClass):
            self.handle = args[0].handle
            _request.IncRef(self.handle)
        elif len(args) == 1 and isinstance(args[0], int):
            self.handle = args[0]
            _request.IncRef(self.handle)
        else:
            self.handle = 0
    def __del__(self):
        _request.DecRef(self.handle)

As a workaround, I was able to make it work by redefining the types in my go package, but it is a bit annoying, since I have to redefine the subtypes in cycletls.Options and rebuild the struct inside the function.