2

I am working on a Python front-end for some existing C++ libraries. As you can imagine, some of the C++ functions use the pass-by-reference method for some arguments. I do not know how to implement this kind of functions into python scripts, namely I should use a pointer to a struct as an argument, but I don't know how.

Note Even though python does not use pointers nor addresses explicitly, cppyy provides a way to access compiled libraries from python scripts. I guess that cppyy also covers this simple case and I am simply missing something like the correct syntax. I am using python 3.10 and cppyy 2.4.2.

Example pconf.h file:

struct Parser_Conf {
  std::string filename      = "";
  uint32_t    dump_addr_st  = 0;
  uint32_t    dump_addr_end = 255;
  bool        debug_session = false;
  bool        use_xterm     = true;
};

void print_conf(Parser_Conf ) ;
void print_conf_fromPtr(Parser_Conf * ) ;

Example pconf.cpp file:

#include <sstream>

struct Parser_Conf {
  std::string filename      = "";
  uint32_t    dump_addr_st  = 0;
  uint32_t    dump_addr_end = 255;
  bool        debug_session = false;
  bool        use_xterm     = true;
};

void print_conf(Parser_Conf ) ;
void print_conf_fromPtr(Parser_Conf * ) ;

Compiled library is in simplebuild/simple/libMINI.so. Example simple.py:

import os
import pysysc
#from cppyy import gbl as cpp
# more readable 
import cppyy
#looks as it is not loaded by default
import cppyy.ll

cppyy.include('boost/any.hpp') 
from cppyy.gbl import std, boost

build_dir= "simplebuild"
name = "PCONF Components"
myDir = os.path.dirname(os.path.realpath(__file__))
buildDir = os.path.join(myDir, build_dir)
program_file_name = "CSRAM_32Bits_macro.ihex"

if (not pysysc.load_systemc(17)):
    print('Error : failed to load systemc dynamic library')
    exit()

print("Loading " + name + " library")
#for HW-2-SW
pysysc.add_include_path(os.path.join(myDir, "simple"))
output = pysysc.add_library("pconf.h", "libMINI.so", buildDir)

parserConfCapsule = boost.any()
print("Preparing a Parser_Conf data")
parserConfCapsule.__assign__(cppyy.gbl.Parser_Conf())

print("Setting up the Parser_Conf data")
parserConfCapsule.type() == cppyy.typeid(cppyy.gbl.Parser_Conf)
print("=> Type of the 'parserConfCapsule' global:", type(parserConfCapsule).__name__)

extract = boost.any_cast[cppyy.gbl.Parser_Conf](parserConfCapsule)
print("=> Type of the 'extract' global:", type(extract).__name__)


print("Setting Parser_Conf fields")
extract.debug_session = False
extract.filename = program_file_name

print("Calling Library function with Parser_Conf struct")
cppyy.gbl.print_conf(extract)

print("Struct instance address is")
print(cppyy.ll.addressof(extract))

addr_of_extract = cppyy.ll.addressof(extract)
print("=> Type of the 'extract' global address:", type(addr_of_extract).__name__)

print("Q:Has the 'extract' global a deref? A:",
      hasattr(extract, '__deref__') or hasattr(extract, 'dereference'))
print("Q:Has the 'extract' global address a deref? A:",
      hasattr(addr_of_extract, '__deref__') or hasattr(addr_of_extract, 'dereference'))

print("Calling Library function with Parser_Conf address")
cppyy.gbl.print_conf_fromPtr(addr_of_extract)

Current output :

gre057823/PySysC-SC 236 >>python3 simple_example.py

        SystemC 2.3.4-Accellera --- Jul  2 2025 14:37:58
        Copyright (c) 1996-2022 by all Contributors,
        ALL RIGHTS RESERVED
Loading PCONF Components library
Preparing a Parser_Conf data
Setting up the Parser_Conf data
=> Type of the 'parserConfCapsule' global: any
=> Type of the 'extract' global: Parser_Conf
Setting Parser_Conf fields
Calling Library function with Parser_Conf struct
Dump range : 0 - FF
Struct instance address is
93974867696144
=> Type of the 'extract' global address: int
Q:Has the 'extract' global a deref? A: False
Q:Has the 'extract' global address a deref? A: False
Calling Library function with Parser_Conf address
Traceback (most recent call last):
  File "/home/360.1.417-StorAIge/USERS/lc177705/PySysC_TREE/PySysC-SC/simple_example.py", line 59, in <module>
    cppyy.gbl.print_conf_fromPtr(addr_of_extract)
TypeError: void ::print_conf_fromPtr(Parser_Conf*) =>
    TypeError: could not convert argument 1

I tried RTFM (https://cppyy.readthedocs.io/en/latest/lowlevel.html) but could not find a solution, any hints welcome.

2 Answers 2

2

You can’t pass the raw integer address — print_conf_fromPtr expects a Parser_Conf*. With cppyy, use the reference operator instead of addressof: cppyy.gbl.print_conf_fromPtr(cppyy.addressof(extract))

gives an int, which is wrong. Instead: cppyy.gbl.print_conf_fromPtr(cppyy.addressof(extract).reinterpret_as(cppyy.gbl.Parser_Conf*))

wrapped as a cppyy pointer type.

you need to pass a Parser_Conf*, not an integer — use reinterpret_as (or cppyy.bind_object(addr, cppyy.gbl.Parser_Conf*)) to cast.

Sign up to request clarification or add additional context in comments.

1 Comment

I understand this is the point, but if I try cppyy.gbl.print_conf_fromPtr(cppyy.addressof(extract).reinterpret_as(cppyy.gbl.Parser_Conf *)) I get a python SyntaxError: invalid syntax at the * character
0

Thanks to @Learn N Spread, that was the point, just it needs a bit of further work (see comment), this is the correct way to solve the issue:

ptrLikeStuff = cppyy.ll.reinterpret_cast['Parser_Conf *'](cppyy.addressof(extract))
print("=> Type of the 'ptrLikeStuff' global:", type(ptrLikeStuff).__name__)
cppyy.gbl.print_conf_fromPtr(ptrLikeStuff)

I tried to edit your answer but moderators say it does not make sense, so I am posting a new answer.

Best regards,

Lorenzo

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.