Skip to content

RuntimeBinderException - Cannot implicitly convert type 'Python.Runtime.PyObject' to 'System.Collections.Generic.List<string>' #451

Closed

Description

@tomhunter-gh

Environment

  • Pythonnet version: 2.3.0
  • Python version: 3.6 (Anaconda 32-bit)
  • Operating System: Windows 10

Details

I have the following code:

Interface1.cs

using System.Collections.Generic;

public interface Interface1
{
    string Test();

    List<string> GetList();

    List<MyType> GetListOfMyType();
}

public class MyType
{
}

Class1.cs

using System.Collections.Generic;

namespace Python.EmbeddingTest
{
    public class Class1 : Interface1
    {
        public string Test()
        {
            return "test";
        }

        public List<string> GetList()
        {
            return new List<string>() { "testing" };
        }

        public List<MyType> GetListOfMyType()
        {
            return new List<MyType>() { new MyType(), new MyType() };
        }
    }
}

Module1.py

import clr

clr.AddReference("Python.EmbeddingTest")
from Python.EmbeddingTest import *

class Class2(Class1):

    def Test(self):
        return "Test from Class2"
    
    def Method1(self):
        return "Method1"

Test

I am trying to do something like what the following test is trying to do:

[Test]
public void TestGenericListMarshalling()
{
    var scope = Py.Import("module1");
    var attr = scope.GetAttr("Class2");
    dynamic c2 = attr.Invoke();
    List<string> ls = c2.GetList();
}

Exception

However, I get the following exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException occurred
  HResult=0x80131500
  Message=Cannot implicitly convert type 'Python.Runtime.PyObject' to 'System.Collections.Generic.List<string>'
  Source=Python.EmbeddingTest
  StackTrace:
   at Python.EmbeddingTest.PyImportTest.TestGenericListMarshalling() in D:\Users\Tom\Dropbox\Algo Trading\pythonnet\src\embed_tests\pyimport.cs:line 90

Is it possible to marshall generic .NET Lists?

Activity

  1. den-run-ai commented on Apr 5, 2017

    @den-run-ai
    Contributor

    @tomhunter-gh can you try from the master?

    pip install git+https://github.com/pythonnet/pythonnet -U --force

    This should have been fixed recently:
    #427

  2. tomhunter-gh commented on Apr 6, 2017

    @tomhunter-gh
    Author

    Hi @denfromufa

    I pulled latest from master but I'm afraid I still get the problem. It looks like casting to a string[] array is successful, but the C# base class (and interface) are defined with a List<string> so I was expecting to be able to cast the dynamic back to a List<string>..

    image

    Were you able to reproduce the issue? What I did was I added the Interface1.cs, Class1.cs, Module.py to the Python.EmbeddingTest project. (By the way, in that project, any reason the 'fixtures' folder is not included in the project file?)

    Thanks

  3. den-run-ai commented on Apr 6, 2017

    @den-run-ai
    Contributor

    @tomhunter-gh can you share your full project in a zip file? just paste it here to this issue.

    fixtures are not included because it is python code, but could be included as a resource. we have a separate pyproj in the directory with python tests.

  4. tomhunter-gh commented on Apr 6, 2017

    @tomhunter-gh
    Author

    By the way I'm using Python 3.6 32-bit, so you may need to change settings in the Python.Runtime project file.

    My test is in: pythonnet\src\embed_tests\pyimport.cs

    Thanks

  5. den-run-ai commented on Apr 7, 2017

    @den-run-ai
    Contributor

    @tomhunter-gh actually that pull request which I linked above #427 leads to this issue :(

    Here is the code that I commented out to pass your the test:

                /*if (value is IList && value.GetType().IsGenericType)
                {
                    using (var resultlist = new PyList())
                    {
                        foreach (object o in (IEnumerable)value)
                        {
                            using (var p = new PyObject(ToPython(o, o?.GetType())))
                            {
                                resultlist.Append(p);
                            }
                        }
                        Runtime.XIncref(resultlist.Handle);
                        return resultlist.Handle;
                    }
                }*/
    

    The reason is because before the list is passed back to C#, it gets converted to Python list.

    So quick workaround would be to provide equivalent conversion from Python to C#: list -> List.

    But this is of course a lot of conversion back and forth and maybe a performance issue.

  6. den-run-ai commented on Apr 7, 2017

    @den-run-ai
    Contributor

    This is rather hackish workaround, but passes all tests! Use at your own risk :)

    pythonnet_hackish.zip

  7. tomhunter-gh commented on Apr 7, 2017

    @tomhunter-gh
    Author

    Thanks @denfromufa - that has fixed the issue!

    Here's the change in case anyone else needs it:

    image

    (You also need to add a reference to Microsoft.CSharp.)

    image

    Thanks

  8. den-run-ai commented on Jul 20, 2017

    @den-run-ai
    Contributor

    related issue:

    #514

  9. added this to the 3.0.0 milestone on Sep 23, 2021
  10. lostmsu commented on Sep 23, 2021

    @lostmsu
    Member

    I believe this should already be fixed in 3.0, but we need a test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions