wlav / cppyy

Other
400 stars 41 forks source link

Can't call main function #98

Closed giulio98 closed 1 year ago

giulio98 commented 1 year ago

Hello, I was trying to use cppyy for a simple experiment, after installing cppyy using pip pip install cppyy

I tried to execute the following code in python

`cppyy.cppdef('''

include <bits/stdc++.h>

using namespace std ; int maxPresum ( vector < int > a , vector < int > b ) { int X = max ( a [ 0 ] , 0 ) ; for ( int i = 1 ; i < a . size ( ) ; i ++ ) { a [ i ] += a [ i - 1 ] ; X = max ( X , a [ i ] ) ; } int Y = max ( b [ 0 ] , 0 ) ; for ( int i = 1 ; i < b . size ( ) ; i ++ ) { b [ i ] += b [ i - 1 ] ; Y = max ( Y , b [ i ] ) ; } return X + Y ; } int main ( ) { vector < int > A = { 2 , -1 , 4 , -5 } ; vector < int > B = { 4 , -3 , 12 , 4 , -3 } ; cout << maxPresum ( A , B ) << endl ; } ''')`

but when calling the main by running cppyy.gbl.main(), it crashes

Instead if I first call the function maxPreSum cppyy.gbl.maxPresum([0],[0] and then the main cppyy.gbl.main() it works fine.

I was wondering why I should call first the function and then the main to make it work

wlav commented 1 year ago

Don't use main, as it has special meaning (can only be one main in a C program and in this case, it's Python's main). Call it anything else other than main.

I presume the difference is that in the second case, main gets added to the JIT symbols when the transaction containing maxPresum is processed for its lookup. Since the JIT symbols are separate from linker symbols, I can see how that could technically work. Doesn't change the fact that you shouldn't use main.

giulio98 commented 1 year ago

Thank you for the quick reply, also I have another question, I am working on code generation and I have to evaluate the functionality of generated programs written in C++ by executing them and compare against the desired output. I think cppyy could be of great help, but let's say that I have 200 samples for maxPresum function, I noticed that starting from the second sample I have to evaluate, I redefine the function using cppyy.cppdef but I get an error because this function is already defined. How I can "overwrite" the definition of a function in cppyy or alternatively delete the previous definition for one that is new?

wlav commented 1 year ago

Offloading, or even better yet, isolated transactions, are a work-in-progress at the Cling level and I suspect it to be some time in the future yet (e.g. with the move jitlink). It's a common request. For now, only variables can be redefined and there's limited offloading of code that lives in shared libraries.

If this is just for testing purposes, then the memory cost shouldn't matter and the easiest would be to use a wrapper that puts code into namespaces. Something along the lines of:

import cppyy

class IsolatedCppDef:
    def __init__(self, prefix="test"):
        self.prefix = prefix
        self.counter = 0

    def __call__(self, code):
        ns = self.prefix+str(self.counter)
        self.counter += 1

        cppyy.cppdef(
            ("namespace %s {" % ns) + code + "}")

        return getattr(cppyy.gbl, ns)

isolated_cppdef = IsolatedCppDef()

for code in [
       "int myfunc() { return 42; }",
       "int myfunc() { return 27; }"]:
    ns = isolated_cppdef(code)
    print(ns.myfunc())

Of course, Python being Python (and thus replacement being easy), you can also place ns.myfunc into cppyy.gbl.myfunc by simple assignment if further downstream testing code relies on that.

giulio98 commented 1 year ago

Thank you very much 😊 I'm closing this issue.