Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions python/cppyy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
__all__ = [
'cppdef', # declare C++ source to Cling
'cppexec', # execute a C++ statement
'macro', # attempt to evaluate a cpp macro
'include', # load and jit a header file
'c_include', # load and jit a C header file
'load_library', # load a shared library
Expand Down Expand Up @@ -234,6 +235,20 @@ def cppexec(stmt):

return True

def macro(cppm):
"""Attempt to evalute a C/C++ pre-processor macro as a constant"""

try:
macro_val = getattr(getattr(gbl, '__cppyy_macros', None), cppm+'_', None)
if macro_val is None:
cppdef("namespace __cppyy_macros { auto %s_ = %s; }" % (cppm, cppm))
return getattr(getattr(gbl, '__cppyy_macros'), cppm+'_')
except Exception:
pass

raise ValueError('Failed to evaluate macro %s', cppm)


def load_library(name):
"""Explicitly load a shared library."""
with _stderr_capture() as err:
Expand Down
10 changes: 9 additions & 1 deletion python/cppyy/_cpython_cppyy.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,13 @@ def _begin_capture_stderr():
def _end_capture_stderr():
err = _backend._end_capture_stderr()
if err:
return "\n%s" % err
try:
return "\n%s" % err
except UnicodeDecodeError as e:
original_error = e
try:
return "\n%s" % err.decode('gbk') # not guaranteed, but common
except UnicodeDecodeError:
pass
return "C++ issued an error message that could not be decoded (%s)" % str(original_error)
return ""
2 changes: 1 addition & 1 deletion python/cppyy/ll.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def argc():
return len(sys.argv)

# import low-level python converters
for _name in ['addressof', 'as_cobject', 'as_capsule', 'as_ctypes']:
for _name in ['addressof', 'as_cobject', 'as_capsule', 'as_ctypes', 'as_memoryview']:
try:
exec('%s = cppyy._backend.%s' % (_name, _name))
__all__.append(_name)
Expand Down
4 changes: 2 additions & 2 deletions test/cpp11features.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ void implicit_converion_move(TestMoving2&&);

//===========================================================================
struct TestData { // for initializer list construction
TestData(int i) : m_int(i) {}
TestData(int i=0) : m_int(i) {}
int m_int;
};

struct TestData2 {
TestData2(int i) : m_int(i) {}
TestData2(int i=0) : m_int(i) {}
virtual ~TestData2() {}
int m_int;
};
Expand Down
52 changes: 40 additions & 12 deletions test/datatypes.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ CppyyTestData::CppyyTestData() : m_const_int(17), m_owns_arrays(false)
#if __cplusplus > 201402L
m_byte_array2 = new std::byte[N];
#endif
m_int8_array2 = new int8_t[N];
m_uint8_array2 = new uint8_t[N];
m_short_array2 = new short[N];
m_ushort_array2 = new unsigned short[N];
m_int_array2 = new int[N];
Expand All @@ -66,18 +68,22 @@ CppyyTestData::CppyyTestData() : m_const_int(17), m_owns_arrays(false)
m_byte_array[i] = (std::byte)(3u*i);
m_byte_array2[i] = (std::byte)(4u*i);
#endif
m_short_array[i] = -1*i;
m_short_array2[i] = -2*i;
m_ushort_array[i] = 3u*i;
m_ushort_array2[i] = 4u*i;
m_int_array[i] = -5*i;
m_int_array2[i] = -6*i;
m_uint_array[i] = 7u*i;
m_uint_array2[i] = 8u*i;
m_long_array[i] = -9l*i;
m_long_array2[i] = -10l*i;
m_ulong_array[i] = 11ul*i;
m_ulong_array2[i] = 12ul*i;
m_int8_array[i] = - 1*i;
m_int8_array2[i] = - 2*i;
m_uint8_array[i] = 3u*i;
m_uint8_array2[i] = 4u*i;
m_short_array[i] = - 5*i;
m_short_array2[i] = - 6*i;
m_ushort_array[i] = 7u*i;
m_ushort_array2[i] = 8u*i;
m_int_array[i] = - 9*i;
m_int_array2[i] = -10*i;
m_uint_array[i] = 11u*i;
m_uint_array2[i] = 23u*i;
m_long_array[i] = -13l*i;
m_long_array2[i] = -14l*i;
m_ulong_array[i] = 15ul*i;
m_ulong_array2[i] = 18ul*i;

m_float_array[i] = -13.f*i;
m_float_array2[i] = -14.f*i;
Expand Down Expand Up @@ -107,6 +113,8 @@ void CppyyTestData::destroy_arrays() {
#if __cplusplus > 201402L
delete[] m_byte_array2;
#endif
delete[] m_int8_array2;
delete[] m_uint8_array2;
delete[] m_short_array2;
delete[] m_ushort_array2;
delete[] m_int_array2;
Expand Down Expand Up @@ -166,6 +174,10 @@ unsigned char* CppyyTestData::get_uchar_array2() { return m_uchar_array2; }
std::byte* CppyyTestData::get_byte_array() { return m_byte_array; }
std::byte* CppyyTestData::get_byte_array2() { return m_byte_array2; }
#endif
int8_t* CppyyTestData::get_int8_array() { return m_int8_array; }
int8_t* CppyyTestData::get_int8_array2() { return m_int8_array2; }
uint8_t* CppyyTestData::get_uint8_array() { return m_uint8_array; }
uint8_t* CppyyTestData::get_uint8_array2() { return m_uint8_array2; }
short* CppyyTestData::get_short_array() { return m_short_array; }
short* CppyyTestData::get_short_array2() { return m_short_array2; }
unsigned short* CppyyTestData::get_ushort_array() { return m_ushort_array; }
Expand Down Expand Up @@ -366,6 +378,8 @@ void CppyyTestData::set_uchar_p(unsigned char* uc) { *uc = 'd'; }
#if __cplusplus > 201402L
void CppyyTestData::set_byte_p(std::byte* b) { *b = (std::byte)'e'; }
#endif
void CppyyTestData::set_int8_p(int8_t* i8) { *i8 = -27; }
void CppyyTestData::set_uint8_p(uint8_t* ui8) { *ui8 = 28; }
void CppyyTestData::set_short_p(short* s) { *s = -1; }
void CppyyTestData::set_ushort_p(unsigned short* us) { *us = 2; }
void CppyyTestData::set_int_p(int* i) { *i = -3; }
Expand Down Expand Up @@ -413,6 +427,14 @@ void CppyyTestData::set_byte_ppa(std::byte** b) {
(*b)[0] = (std::byte)'n'; (*b)[1] = (std::byte)'o'; (*b)[2] = (std::byte)'p';
}
#endif
void CppyyTestData::set_int8_ppa(int8_t** i8) {
(*i8) = new int8_t[3];
(*i8)[0] = -27; (*i8)[1] = -28; (*i8)[2] = -29;
}
void CppyyTestData::set_uint8_ppa(uint8_t** ui8) {
(*ui8) = new uint8_t[3];
(*ui8)[0] = 28; (*ui8)[1] = 29; (*ui8)[2] = 30;
}
void CppyyTestData::set_short_ppa(short** s) {
(*s) = new short[3];
(*s)[0] = -1; (*s)[1] = -2; (*s)[2] = -3;
Expand Down Expand Up @@ -1015,3 +1037,9 @@ MULTIDIM_ARRAYS_NEW2D(long long, llong)
MULTIDIM_ARRAYS_NEW2D(unsigned long long, ullong)
MULTIDIM_ARRAYS_NEW2D(float, float)
MULTIDIM_ARRAYS_NEW2D(double, double)

//===========================================================================
namespace Int8_Uint8_Arrays {
int8_t test[6] = {-0x12, -0x34, -0x56, -0x78};
uint8_t utest[6] = { 0x12, 0x34, 0x56, 0x78};
}
19 changes: 19 additions & 0 deletions test/datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ class CppyyTestData {
std::byte* get_byte_array();
std::byte* get_byte_array2();
#endif
int8_t* get_int8_array();
int8_t* get_int8_array2();
uint8_t* get_uint8_array();
uint8_t* get_uint8_array2();
short* get_short_array();
short* get_short_array2();
unsigned short* get_ushort_array();
Expand Down Expand Up @@ -340,6 +344,8 @@ class CppyyTestData {
#if __cplusplus > 201402L
void set_byte_p(std::byte*);
#endif
void set_int8_p(int8_t*);
void set_uint8_p(uint8_t*);
void set_short_p(short*);
void set_ushort_p(unsigned short*);
void set_int_p(int*);
Expand All @@ -363,6 +369,8 @@ class CppyyTestData {
#if __cplusplus > 201402L
void set_byte_ppa(std::byte**);
#endif
void set_int8_ppa(int8_t**);
void set_uint8_ppa(uint8_t**);
void set_short_ppa(short**);
void set_ushort_ppa(unsigned short**);
void set_int_ppa(int**);
Expand Down Expand Up @@ -498,6 +506,10 @@ class CppyyTestData {
std::byte m_byte_array[N];
std::byte* m_byte_array2;
#endif
int8_t m_int8_array[N];
int8_t* m_int8_array2;
uint8_t m_uint8_array[N];
uint8_t* m_uint8_array2;
short m_short_array[N];
short* m_short_array2;
unsigned short m_ushort_array[N];
Expand Down Expand Up @@ -843,4 +855,11 @@ struct DataHolder {

} // namespace MultiDimArrays


//= int8_t/uint8_t arrays ===================================================
namespace Int8_Uint8_Arrays {
extern int8_t test[6];
extern uint8_t utest[6];
}

#endif // !CPPYY_TEST_DATATYPES_H
18 changes: 0 additions & 18 deletions test/stltypes.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,6 @@

#include <string.h>


//- explicit instantiations of used comparisons
#if defined __clang__ || defined(__GNUC__) || defined(__GNUG__)
#if defined __clang__
namespace std {
#define ns_prefix std::
#elif defined(__GNUC__) || defined(__GNUG__)
namespace __gnu_cxx {
#define ns_prefix
#endif
template bool ns_prefix operator==(const std::vector<int>::iterator&,
const std::vector<int>::iterator&);
template bool ns_prefix operator!=(const std::vector<int>::iterator&,
const std::vector<int>::iterator&);
}
#endif


//- adverse effect of implicit conversion on vector<string>
int vectest_ol1(const std::vector<std::string>&) { return 1; }
int vectest_ol1(std::string) { return 2; }
Expand Down
12 changes: 12 additions & 0 deletions test/test_advancedcpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,10 @@ def test29_castcpp(self):
return std::sqrt(p.x*p.x + p.y*p.y);
}

double norm_m(MyPoint&& p) {
return std::sqrt(p.x*p.x + p.y*p.y);
}

double norm_v(MyPoint p) {
return std::sqrt(p.x*p.x + p.y*p.y);
}
Expand All @@ -945,8 +949,13 @@ class MyPyPoint2(MyPyPoint1):
def __cast_cpp__(self):
return ns.MyPoint(self.x, self.y)

class MyPyPoint3(MyPyPoint1):
def __cast_cpp__(self):
return (self.x, self.y)

p1 = MyPyPoint1(5, 10)
p2 = MyPyPoint2(p1.x, p1.y)
p3 = MyPyPoint3(p1.x, p1.y)
pynorm = math.sqrt(p2.x**2+p2.y**2)

for norm in [ns.norm_cr, ns.norm_r, ns.norm_v, ns.norm_p]:
Expand All @@ -955,3 +964,6 @@ def __cast_cpp__(self):

assert round(norm(p2) - pynorm, 8) == 0

for norm in [ns.norm_cr, ns.norm_m, ns.norm_v]:
assert round(norm(p3) - pynorm, 8) == 0

29 changes: 29 additions & 0 deletions test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,32 @@ class APICheck4Executor : public CPyCppyy::Executor {
assert a4
assert type(a4) == cppyy.gbl.APICheck4
assert not a4.wasExecutorCalled();

def test06_custom_executor(self):
"""Custom type executor"""

import cppyy

cppyy.cppdef("""
#include "CPyCppyy/API.h"

namespace ArrayLike {
class MyClass{};
MyClass* my = nullptr;
MyClass myA[5];

class MyArray {
public:
int operator[](int) { return 42; }
}; }""")

ns = cppyy.gbl.ArrayLike;
Sequence_Check = cppyy.gbl.CPyCppyy.Sequence_Check

assert not Sequence_Check(ns.my)
assert Sequence_Check(ns.myA)
assert not Sequence_Check(ns.MyClass())
assert Sequence_Check(ns.MyArray())
assert Sequence_Check(tuple())
assert Sequence_Check(cppyy.gbl.std.vector[ns.MyClass]())
assert not Sequence_Check(cppyy.gbl.std.list[ns.MyClass]())
27 changes: 27 additions & 0 deletions test/test_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,30 @@ def test04_implicit_conversion_from_tuple(self):
m.insert(('a', 'b')) # implicit conversion to std::pair

assert m['a'] == 'b'

def test05_bool_conversions(self):
"""Test operator bool() and null pointer behavior"""

import cppyy

cppyy.cppdef("""\
namespace BoolConversions {
struct Test1 {};
struct Test2 {
Test2(bool b) : m_b(b) {}
explicit operator bool() const { return m_b; }
bool m_b;
};

Test1* CreateNullTest1() { return nullptr; }
Test2* CreateNullTest2() { return nullptr; }
}""")

ns = cppyy.gbl.BoolConversions

for t in [ns.CreateNullTest1(), ns.CreateNullTest2()]:
assert not t

assert ns.Test1()
assert ns.Test2(True)
assert not ns.Test2(False)
Loading
Loading