Skip to content

Commit

Permalink
Fix bugs introduced by 73cbd9b (PR #14)
Browse files Browse the repository at this point in the history
  • Loading branch information
wlav committed Apr 4, 2024
1 parent 63c1d53 commit fce87d5
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 53 deletions.
115 changes: 69 additions & 46 deletions src/Converters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1866,53 +1866,7 @@ bool CPyCppyy::name##Converter::ToMemory( \
}

CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(STLString, std::string, c_str, size)
#if __cplusplus > 201402L
CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(STLStringViewBase, std::string_view, data, size)
bool CPyCppyy::STLStringViewConverter::SetArg(
PyObject* pyobject, Parameter& para, CallContext* ctxt)
{
if (this->STLStringViewBaseConverter::SetArg(pyobject, para, ctxt)) {
// One extra step compared to the regular std::string converter:
// Create a corresponding std::string_view and set the parameter value
// accordingly.
fStringView = *reinterpret_cast<std::string*>(para.fValue.fVoidp);
para.fValue.fVoidp = &fStringView;
return true;
}

if (!CPPInstance_Check(pyobject))
return false;

static Cppyy::TCppScope_t sStringID = Cppyy::GetScope("std::string");
CPPInstance* pyobj = (CPPInstance*)pyobject;
if (pyobj->ObjectIsA() == sStringID) {
void* ptr = pyobj->GetObject();
if (!ptr)
return false;

// Copy the string to ensure the lifetime of the string_view and the
// underlying string is identical.
fStringBuffer = *((std::string*)ptr);
// Create the string_view on the copy
fStringView = fStringBuffer;
para.fValue.fVoidp = &fStringView;
para.fTypeCode = 'V';
return true;
}

return false;
}
bool CPyCppyy::STLStringViewConverter::ToMemory(
PyObject* value, void* address, PyObject* ctxt)
{
if (CPyCppyy_PyUnicodeAsBytes2Buffer(value, fStringBuffer)) {
fStringView = fStringBuffer;
*reinterpret_cast<std::string_view*>(address) = fStringView;
return true;
}
return InstanceConverter::ToMemory(value, address, ctxt);
}
#endif

CPyCppyy::STLWStringConverter::STLWStringConverter(bool keepControl) :
InstanceConverter(Cppyy::GetScope("std::wstring"), keepControl) {}
Expand Down Expand Up @@ -1977,6 +1931,75 @@ bool CPyCppyy::STLWStringConverter::ToMemory(PyObject* value, void* address, PyO
}


#if __cplusplus > 201402L
CPyCppyy::STLStringViewConverter::STLStringViewConverter(bool keepControl) :
InstanceConverter(Cppyy::GetScope("std::string_view"), keepControl) {}

bool CPyCppyy::STLStringViewConverter::SetArg(
PyObject* pyobject, Parameter& para, CallContext* ctxt)
{
// normal instance convertion (ie. string_view object passed)
if (!PyInt_Check(pyobject) && !PyLong_Check(pyobject) && \
InstanceConverter::SetArg(pyobject, para, ctxt)) {
para.fTypeCode = 'V';
return true;
}
PyErr_Clear();

// for Python str object: convert to single char string in buffer and take a view
if (CPyCppyy_PyUnicodeAsBytes2Buffer(pyobject, fStringBuffer)) {
fStringViewBuffer = fStringBuffer;
para.fValue.fVoidp = &fStringViewBuffer;
para.fTypeCode = 'V';
return true;
}

if (!CPPInstance_Check(pyobject))
return false;

// for C++ std::string object: buffer the string and take a view
if (CPPInstance_Check(pyobject)) {
static Cppyy::TCppScope_t sStringID = Cppyy::GetScope("std::string");
CPPInstance* pyobj = (CPPInstance*)pyobject;
if (pyobj->ObjectIsA() == sStringID) {
void* ptr = pyobj->GetObject();
if (!ptr)
return false; // leaves prior conversion error for report

PyErr_Clear();

fStringBuffer = *((std::string*)ptr);
fStringViewBuffer = fStringBuffer;
para.fValue.fVoidp = &fStringViewBuffer;
para.fTypeCode = 'V';
return true;
}
}

return false;
}

PyObject* CPyCppyy::STLStringViewConverter::FromMemory(void* address)
{
if (address)
return InstanceConverter::FromMemory(address);
auto* empty = new std::string_view();
return BindCppObjectNoCast(empty, fClass, CPPInstance::kIsOwner);
}

bool CPyCppyy::STLStringViewConverter::ToMemory(
PyObject* value, void* address, PyObject* ctxt)
{
if (CPyCppyy_PyUnicodeAsBytes2Buffer(value, fStringBuffer)) {
fStringViewBuffer = fStringBuffer;
*reinterpret_cast<std::string_view*>(address) = fStringViewBuffer;
return true;
}
return InstanceConverter::ToMemory(value, address, ctxt);
}
#endif


bool CPyCppyy::STLStringMoveConverter::SetArg(
PyObject* pyobject, Parameter& para, CallContext* ctxt)
{
Expand Down
23 changes: 16 additions & 7 deletions src/DeclareConverters.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ class VoidPtrRefConverter : public Converter {
class VoidPtrPtrConverter : public Converter {
public:
VoidPtrPtrConverter(cdims_t dims);

public:
virtual bool SetArg(PyObject*, Parameter&, CallContext* = nullptr);
virtual PyObject* FromMemory(void* address);
virtual bool HasState() { return true; }
Expand All @@ -351,29 +353,36 @@ CPPYY_DECLARE_BASIC_CONVERTER(PyObject);
class name##Converter : public InstanceConverter { \
public: \
name##Converter(bool keepControl = true); \
\
public: \
virtual bool SetArg(PyObject*, Parameter&, CallContext* = nullptr); \
virtual PyObject* FromMemory(void* address); \
virtual bool ToMemory(PyObject*, void*, PyObject* = nullptr); \
virtual bool HasState() { return true; } \
\
protected: \
strtype fStringBuffer; \
}

CPPYY_DECLARE_STRING_CONVERTER(STLString, std::string);
CPPYY_DECLARE_STRING_CONVERTER(STLWString, std::wstring);

#if __cplusplus > 201402L
// The buffer type needs to be std::string also in the string_view case,
// otherwise the pointed-to string might not live long enough. See also:
// https://github.com/wlav/CPyCppyy/issues/13
CPPYY_DECLARE_STRING_CONVERTER(STLStringViewBase, std::string);
class STLStringViewConverter : public STLStringViewBaseConverter {
class STLStringViewConverter : public InstanceConverter {
public:
STLStringViewConverter(bool keepControl = true);

public:
virtual bool SetArg(PyObject*, Parameter&, CallContext* = nullptr);
virtual PyObject* FromMemory(void* address);
virtual bool ToMemory(PyObject*, void*, PyObject* = nullptr);
virtual bool HasState() { return true; }

private:
std::string_view fStringView;
std::string fStringBuffer; // converted str data
std::string_view fStringViewBuffer; // view on converted data
};
#endif
CPPYY_DECLARE_STRING_CONVERTER(STLWString, std::wstring);

class STLStringMoveConverter : public STLStringConverter {
public:
Expand Down

0 comments on commit fce87d5

Please sign in to comment.