Skip to content

Calling overridden method with out parameter from C# to python results in 0xC0000005 (Access Violation) #1481

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

Closed
roy-van-de-korput opened this issue Jul 5, 2021 · 5 comments · Fixed by #1663
Milestone

Comments

@roy-van-de-korput
Copy link

roy-van-de-korput commented Jul 5, 2021

Environment

  • Pythonnet version: 2.5.2
  • Python version: 3.8.3
  • Operating System: Win10 64bit
  • .NET Runtime: 4.8

Details

  • Describe what you were trying to get done.

In C# I have defined an interface with a method with an out parameter. I implemented this interface in python, an now I want to call this method from C#. (using pythonnet)

What I see is that a method without out parameter works fine, but a method with an out parameter throws an access violation.

I know that out parameters are handled differently in pythonnet: you return a tuple with first the return value and the second tuple item is the out parameter.

My C# code

public interface IMyInterface
{
    string MyMethod_Out(string name, out int index);
    string MyMethod(string name);
}

public class MyServer
{
    public void CallMyMethod_Out(IMyInterface myInterface)
    {
        Console.WriteLine("C#.CallMyMethod_Out: before MyMethod_Out");
        int index = 1;
        myInterface.MyMethod_Out("myclient", out index);
        Console.WriteLine($"C#:CallMyMethod_Out: after MyMethod_Out: index:{index}");
    }
    
    public void CallMyMethod(IMyInterface myInterface)
    {
        Console.WriteLine("C#.CallMyMethod: before MyMethod");
        myInterface.MyMethod("myclient");
        Console.WriteLine($"C#:CallMyMethod: after MyMethod");
    }

    public void DoSomething()
    {
        Console.WriteLine("C#.DoSomething");
    }
}

My Python code:

import clr
import sys

sys.path.append('some_dir')
clr.AddReference("ClassLibrary1")

from ClassLibrary1 import IMyInterface, MyServer

class MyInterfaceImpl(IMyInterface):
    __namespace__ = "ClassLibrary1"

    def MyMethod_Out(self, name, index):
        print("Python.MyInterfaceImpl.MyMethod_Out")
        other_index = 101
        return ('MyName', other_index)

    def MyMethod(self, name):
        print("Python.MyInterfaceImpl.MyMethod")
        return 'MyName'

print('\nCall regular C# function')
my_server = MyServer()
my_server.DoSomething()

my_interface_impl = MyInterfaceImpl()

print('\nCall without out param')
my_server.CallMyMethod(my_interface_impl)

print('\nCall with out param')
my_server.CallMyMethod_Out(my_interface_impl) # Access Violation 0xC0000005
  • If there was a crash, please include the traceback here.
    Output:

Call regular C# function
C#.DoSomething

Call without out param
C#.CallMyMethod: before MyMethod
Python.MyInterfaceImpl.MyMethod
C#:CallMyMethod: after MyMethod

Call with out param
C#.CallMyMethod_Out: before MyMethod_Out
Process finished with exit code -1073741819 (0xC0000005)

Expected output

...
Call with out param
C#.CallMyMethod_Out: before MyMethod_Out
Python.MyInterfaceImpl.MyMethod_Out
C#:CallMyMethod_Out: after MyMethod_Out: index:101

@filmor
Copy link
Member

filmor commented Jul 6, 2021

Can you please test this with the current master? I vaguely remember a similar issue that has been fixed a while ago.

@roy-van-de-korput
Copy link
Author

I just retried with master (ea61b03) . Same error.

@default-writer
Copy link

You are not just override method, you are returning Tuple instead of a String, what whould you expect for that?

return type String:
string MyMethod_Out(string name, out int index);

return type Tuple<String,Int>
return ('MyName', other_index)

@filmor filmor added this to the 3.0.0 milestone Jan 6, 2022
@lostmsu
Copy link
Member

lostmsu commented Jan 6, 2022

This is a very involved issue, that requires dynamic code generation to be rewritten to support byref arguments. For now unless somebody wants to pick it up, I suggest we document it and move along.

As a workaround one can define another interface in .NET that does not have out or ref parameters, and a class serving as an adapter between the original interface and the new one.

lostmsu added a commit to losttech/pythonnet that referenced this issue Jan 6, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes pythonnet#1481
lostmsu added a commit to losttech/pythonnet that referenced this issue Jan 6, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes pythonnet#1481
lostmsu added a commit to losttech/pythonnet that referenced this issue Jan 6, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes pythonnet#1481
lostmsu added a commit to losttech/pythonnet that referenced this issue Jan 6, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes pythonnet#1481
@lostmsu
Copy link
Member

lostmsu commented Jan 6, 2022

😁 I got bored and made #1663

lostmsu added a commit to losttech/pythonnet that referenced this issue Jan 6, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes pythonnet#1481
lostmsu added a commit that referenced this issue Jan 7, 2022
…Python

new code is emitted to
1. unpack the tuple returned from Python to extract new values for byref parameters and modify args array correspondingly
2. marshal those new values from the args array back into arguments in IL

fixes #1481
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

Successfully merging a pull request may close this issue.

4 participants