8000 Exception when passing a custom python object as the parameter · Issue #412 · pythonnet/pythonnet · GitHub
[go: up one dir, main page]

Skip to content

Exception when passing a custom python object as the parameter #412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
yagweb opened this issue Mar 1, 2017 · 5 comments
Open

Exception when passing a custom python object as the parameter #412

yagweb opened this issue Mar 1, 2017 · 5 comments

Comments

@yagweb
Copy link
Contributor
yagweb commented Mar 1, 2017

Environment

  • Pythonnet version: v2.2.2
  • Python version: 3.5 64bit
  • Operating System: Windows 10

Details

I want to call a .NET method from python and pass a python object as the parameter. If the .NET function declare the argument type as PyObject, everything is fine, however, if declare the argument type as object or dynamic, exception raised.

In my project, the exception is “System.OverflowException” in GetManagedObject method in managedtype.cs.
In order to reproduce it, I built a minimal example, but a new exception raised "TypeError : No method matches given arguments".

These two exception may have some relationship, so I put this one here first since it has a way to be reproduced.

public object callback(dynamic _para)    //TypeError : No method matches given arguments
public object callback(object _para)     //TypeError : No method matches given arguments
public object callback(PyObject _para)   //passed

This is similar to this issue and this PR fixed it. I tested it, when passing an int or string object the function of 2nd and 3rd signature can be found, but when passing a python object, exception raised.

Here is the minimal example,

using System;
using Python.Runtime;

namespace pythonnetTest
{
    public class CallbackBug
    {
        public void Main()
        {
            PythonEngine.Initialize();
            using (Py.GIL())
            {
                dynamic sys = PythonEngine.ImportModule("sys");
                sys.attr1 = new Callback();
                PythonEngine.Exec(
                    "import sys\n" +
                    "class template(object):\n" +
                    "    def __init__(self):\n" +
                    "        self.value = None\n" +
                    "    def write(self, msg):\n" +
                    "        self.value = msg\n" +
                    "para = template()\n" +
                    //call .NET method and pass a custom python object as the parameter
                    "sys.attr2 = sys.attr1.callback(para)\n" + 
                    "sys.attr3 = para.value\n"
                );
                Console.WriteLine(sys.attr2.value);
                Console.WriteLine(sys.attr3);
            }
        }
    }
    public class CallbackValue
    {
        public int value;
    }
    public class Callback
    {
        public object callback(dynamic _para)  //TypeError : No method matches given arguments
        //public object callback(object _para) //TypeError : No method matches given arguments
        //public object callback(PyObject _para)   //passed
        {
            using (Py.GIL()) //attension
            {
                dynamic para = _para;
                para.write("123");
            }
            return new CallbackValue() { value = 100};
        }
    }
}
@vmuriart
Copy link
Contributor
vmuriart commented Mar 2, 2017

I wonder if this ever worked. Can you try to reproduce this using v2.0.0(python 2 only) or v.2.1.0.dev0 before #151 (works upto PY34). If you can't thats ok, but it would greatly narrow down where to look to fix this.

@yagweb
Copy link
Contributor Author
yagweb commented Mar 3, 2017

@vmuriart I tested it with v2.0.0 (python2.7) and it failed with the same exception. v2.0.0 performs even worse than the current version, details was given as comments in the test code.

Since there are many API not available in v2.0.0, so I wrote a new test, it's more concise and shown as below.

The origin PythonEngine.RunString method in v2.0.0 has a bug, I fixed it in order to run the test.

namespace pythonnetTest
{
    public class CallbackBug
    {
        public static void TestHighOrderFunction2()
        {
            PythonEngine.Initialize();
            var gil = PythonEngine.AcquireLock();
            PythonEngine.RunString(
                "import sys\n" +
                "class MyInt(object):\n" +
                "    def __init__(self, value):\n" +
                "        self.value = value\n" +
                "from pythonnetTest import CallbackBug\n" +
                "CallbackBug.callback(1)\n" +                //v2.0.0 failed here!
                "CallbackBug.callback_o(1)\n" +
                "CallbackBug.callback_d(1)\n" +
                "CallbackBug.callback(MyInt(2))\n" +          
                "CallbackBug.callback_o(MyInt(2))\n" +       //current master branch failed here!
                "CallbackBug.callback_d(MyInt(2))\n"
            );
            PythonEngine.ReleaseLock(gil);
        }

        public static void callback(PyObject value)
        {
            Console.WriteLine("PyObject passed");
        }
        public static void callback_o(object value)
        {
            Console.WriteLine("object passed");
        }
        public static void callback_d(dynamic value)
        {
            Console.WriteLine("dynamic passed");
        }
    }
}

@yagweb
Copy link
Contributor Author
yagweb commented Mar 3, 2017

@vmuriart By the way, how do you set up the environment to run a code snippet with old version of pythonnet and other version of Python?

@vmuriart
Copy link
Contributor
vmuriart commented Mar 3, 2017

Thanks for testing on v2.0.0. Sadly it didn't show what I hoped though. I'll need to dig a bit more into the code to figure out whats causing it.

irt running on older pythonnet. Usually I write my tests on a *.py and try to run them on py2.7 against the compiled wheels we uploaded to pypi. If i need to dig into specific commits it gets trickier. Normally I check out the commit, upgrade UnmanagedExports if it wasn't on the latest version, and rebuild/install the package against the version I want to test.

Alternatively, you can also add your tests to the test_suite and push to your fork. If you have an account on Travis and/or AppVeyor it should run the tests for you. This only works for tests running from *.py files since the embedded tests weren't working until recently.

@vmuriart
Copy link
Contributor
vmuriart commented Mar 3, 2017

You can setup git bisect run though I have minimal experience w it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0