Search code examples
pythoncppyy

Read char16_t* String with cppyy from c++


cppyy is the only Python package I've found for wrapping a C++ Lib using char16_t* strings under Linux. Given a function:

int ::func1(const char16_t* symbol, char16_t* data, const unsigned int length)
// [in] symbol, [out] data, [in] length
// Returns a string "data" of "length" dependent on keyword "symbol"

How do I read the string "data" from the function? The ctypes-Approach does not work:

length = 10
val = ctypes.create_unicode_buffer(length)
cppyy.gbl.func1('Keyname', val, length)

Worked through the Documentation and managed to wrap everything beside this. Hints very appreciated.


Solution

  • I'm afraid cppyy is trying to be too smart by half in always interpreting char16_t* as a Python unicode string (incl. BOM and Python's specific encoding) and not seeing it as a low-level array or out-parameter. I can probably fix/improve some of that, but for now, here's a work-around to get you past this point:

    import cppyy
    import cppyy.ll
    
    cppyy.cppdef("""
    int func1_wrap(const char16_t* symbol, void* data, const unsigned int length) {
        return func1(symbol, (char16_t*)data, length);
    }
    """)
    
    def func1_pywrap(symbol, length):
        buf = cppyy.ll.array_new[cppyy.gbl.uint16_t](length)
        res = cppyy.gbl.func1_wrap(symbol, buf, length)
        return res, cppyy.ll.cast['char16_t*'](buf)
    
    cppyy.gbl.func1 = func1_pywrap
    
    result = cppyy.gbl.func1('Keyname', 5)
    print(result)
    

    The various casts are simply to make cppyy blind to the fact it's dealing with a unicode string, and simply make it pass pointers around.