bcdev / jpy

A bi-directional Python-Java bridge used to embed Java in CPython or the other way round.
Apache License 2.0
187 stars 37 forks source link

unsupported operand type(s) for +: 'int' and 'int' #122

Open stevekew opened 6 years ago

stevekew commented 6 years ago

Hi, first, thanks for the great project.

I'm trying to call a python script from Java. I have setup everything in Java and can call basic methods in python with no issue. However I'm having a problem trying to do basic arithmetic. If I try to add two python values, it works fine, but when I try to add values passed in from java I get this error

Exception in thread "main" java.lang.RuntimeException: Error in Python interpreter: Type: <type 'exceptions.TypeError'> Value: unsupported operand type(s) for +: 'int' and 'int' Line: 15 Namespace: calc File: /Projects/java/pytest/scripts/calculator.py at org.jpy.PyLib.callAndReturnValue(Native Method) at org.jpy.PyProxyHandler.invoke(PyProxyHandler.java:56) at net.$Proxy0.calc(Unknown Source) at net.TestMain.main(TestMain.java:58)

It seems that python doesn't like the integers being passed across.

The python script looks like this

def calc(a, b): print type(a) val = 2 print type(val) y = a print type(y) print val return a + b

And I'm calling it via a proxy class

interface Calculator { void initialise(); int calc(int val, int val2); }

like so

PyModule module = PyModule.importModule("calculator");

Calculator calculator = module.createProxy(Calculator.class);

if(calculator != null) { calculator.initialise(); int val = calculator.calc(1, 3);

System.out.println("Calc=" + val); }

I was wondering if i am doing something wrong, or if there is an issue here?

thanks

Steve

gchamon commented 6 years ago

I am also having trouble with that. The object that is being passed to the method is an int, but not a python primitive, but a java int primitive. I am trying all too desperately to convert the passed argument to something Python can work with, either numpy or whatever, because I'll have to pass big arrays of floats for calculation, and I see that there is no documentation covering how to pass arguments from Java to Python using interfaces.

The problem might be the actual use of interfaces. Perhaps just declaring a function and executing it with PyModule's call method could solve the problem

gchamon commented 6 years ago

That is it.

    @Test
    public void testAddOneInPython() {
        PyModule testFunctionsModule = PyModule.importModule("testFunctions");
        PyObject result = testFunctionsModule.call("add_one", 1);
        assertNotEquals(1, result.getIntValue());
        assertEquals(2, result.getIntValue());
    }

with testFunctions.py:

def add_one(x)
    return x + 1

works.

I wonder how I could do the same with interfaces.

gchamon commented 6 years ago

hacky workaround: a_int = int("%s" % a)

gchamon commented 6 years ago

correct way:

interface Calculator {
    void initialise();
    int calc(Integer val, Integer val2);
}