diff --git a/kcardgame/CMakeLists.txt b/kcardgame/CMakeLists.txt new file mode 100644 index 00000000..b8b6417d --- /dev/null +++ b/kcardgame/CMakeLists.txt @@ -0,0 +1,40 @@ +project(minimal) + +set(minimal_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_minimal.xml +) + +set(minimal_SRC +${CMAKE_CURRENT_BINARY_DIR}/minimal/minimal_module_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/obj_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/val_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/listuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/minimal/minbooluser_wrapper.cpp +) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/minimal-binding.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt" @ONLY) + +add_custom_command(OUTPUT ${minimal_SRC} +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'minimal' test binding..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libminimal_SOURCE_DIR} + ${libshiboken_SOURCE_DIR} + ${libshiboken_BINARY_DIR}) +add_library(minimal MODULE ${minimal_SRC}) +set_property(TARGET minimal PROPERTY PREFIX "") +set_property(TARGET minimal PROPERTY OUTPUT_NAME "minimal${PYTHON_EXTENSION_SUFFIX}") +if(WIN32) + set_property(TARGET minimal PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(minimal + libminimal + ${SBK_PYTHON_LIBRARIES} + libshiboken) diff --git a/kcardgame/Makefile b/kcardgame/Makefile index b36124ad..3fe34496 100644 --- a/kcardgame/Makefile +++ b/kcardgame/Makefile @@ -4,4 +4,4 @@ kcardgame.so: kcardgame.o Makefile # ---- gcc C compile ------------------ kcardgame.o: kcardgame.cpp kcardgame.hpp Makefile - gcc `pkg-config --cflags Qt5Gui` -I build-kpat/libkcardgame/ -I kpat/libkcardgame/include -I kpat/libkcardgame/ -g -fPIC -c kcardgame.cpp -I /usr/include/python3.7m/ -I /usr/lib64/python3.7/site-packages/numpy/core/include/numpy + gcc `pkg-config --cflags Qt5Gui pyside2` -I /usr/include/PySide2/QtCore/ -I /usr/include/PySide2/QtGui/ -I build-kpat/libkcardgame/ -I kpat/libkcardgame/include -I kpat/libkcardgame/ -g -fPIC -c kcardgame.cpp -I /usr/include/python3.7m/ -I /usr/lib64/python3.7/site-packages/numpy/core/include/numpy diff --git a/kcardgame/binding-example/CMakeLists.txt b/kcardgame/binding-example/CMakeLists.txt new file mode 100644 index 00000000..924fe570 --- /dev/null +++ b/kcardgame/binding-example/CMakeLists.txt @@ -0,0 +1,125 @@ +project(kcardgame) +cmake_minimum_required(VERSION 3.12) +cmake_policy(VERSION 3.12) + +find_package(ECM 5 REQUIRED CONFIG) +find_package(Qt5 COMPONENTS Core REQUIRED) + +get_target_property(QtCore_location Qt5::Core LOCATION) +get_filename_component(QtCore_libdir ${QtCore_location} DIRECTORY) + +set(CMAKE_AUTOMOC ON) + +project(Shiboken2-Qt-Example) + +set(CMAKE_CXX_STANDARD 11) +set(sample_library "libexamplebinding") +set(bindings_library "Shiboken2QtExample") +set(wrapped_header ${CMAKE_SOURCE_DIR}/bindings.h) +set(typesystem_file ${CMAKE_SOURCE_DIR}/bindings.xml) +set(generated_sources + ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/qobjectwithenum_wrapper.cpp + ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/shiboken2qtexample_module_wrapper.cpp) + +find_package(Python3 REQUIRED COMPONENTS Interpreter Development) + +if(NOT python_interpreter) + find_program(python_interpreter "python33") +endif() + +set(PYSIDE2_DIR ${Python3_SITELIB}/PySide2) + +macro(pyside2_config option output_var) + if(${ARGC} GREATER 2) + set(is_list ${ARGV2}) + else() + set(is_list "") + endif() + + execute_process( + COMMAND ${python_interpreter} "${PYSIDE2_DIR}/examples/utils/pyside2_config.py" + ${option} + OUTPUT_VARIABLE ${output_var} + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if ("${${output_var}}" STREQUAL "") + message(FATAL_ERROR "Error: Calling pyside2_config.py ${option} returned no output.") + endif() + if(is_list) + string (REPLACE " " ";" ${output_var} "${${output_var}}") + endif() +endmacro() + +if () +pyside2_config(--shiboken2-module-path shiboken2_module_path) +pyside2_config(--shiboken2-generator-path shiboken2_generator_path) +pyside2_config(--python-include-path python_include_dir) +pyside2_config(--shiboken2-generator-include-path shiboken_include_dir 1) +pyside2_config(--shiboken2-module-shared-libraries-cmake shiboken_shared_libraries 0) +pyside2_config(--pyside2-shared-libraries-cmake pyside2_link 0) +endif() +set(shiboken_path "/usr/bin/shiboken2${CMAKE_EXECUTABLE_SUFFIX}") +if(NOT EXISTS ${shiboken_path}) + message(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}") +endif() + +set(CMAKE_SKIP_BUILD_RPATH FALSE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(CMAKE_INSTALL_RPATH ${shiboken2_module_path} ${CMAKE_CURRENT_SOURCE_DIR} ${QtCore_libdir}) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +set(${sample_library}_sources qobjectwithenum.cpp) +add_library(${sample_library} SHARED ${${sample_library}_sources}) +target_link_libraries(${sample_library} Qt5::Core) +set_property(TARGET ${sample_library} PROPERTY PREFIX "") + +get_target_property(qtcore_lib_includes Qt5::Core INTERFACE_INCLUDE_DIRECTORIES) +list(JOIN qtcore_lib_includes ";-I" lib_includes) +set(lib_includes "-I${lib_includes}") + +target_compile_definitions(${sample_library} PRIVATE BINDINGS_BUILD) + + +set(shiboken_options --generator-set=shiboken --enable-parent-ctor-heuristic + --enable-return-value-heuristic --use-isnull-as-nb_nonzero + --avoid-protected-hack + --enable-pyside-extensions + ${lib_includes} + -I${CMAKE_SOURCE_DIR} + -T${CMAKE_SOURCE_DIR} + -T${PYSIDE2_DIR}/typesystems/ + --output-directory=${CMAKE_CURRENT_BINARY_DIR} + ) + +set(generated_sources_dependencies ${wrapped_header} ${typesystem_file}) + +add_custom_command(OUTPUT ${generated_sources} + COMMAND ${shiboken_path} + ${shiboken_options} ${wrapped_header} ${typesystem_file} + DEPENDS ${generated_sources_dependencies} + IMPLICIT_DEPENDS CXX ${wrapped_header} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Running generator for ${typesystem_file}.") + +set(${bindings_library}_sources ${generated_sources}) + +add_library(${bindings_library} MODULE ${${bindings_library}_sources}) + +target_include_directories(${bindings_library} PRIVATE ${python_include_dir}) +target_include_directories(${bindings_library} PRIVATE ${PYSIDE2_DIR}/include/) +target_include_directories(${bindings_library} PRIVATE ${PYSIDE2_DIR}/include/QtCore) +target_include_directories(${bindings_library} PRIVATE ${shiboken_include_dir}) +target_include_directories(${bindings_library} PRIVATE ${CMAKE_SOURCE_DIR}) + +target_link_libraries(${bindings_library} PRIVATE ${shiboken_shared_libraries}) +target_link_libraries(${bindings_library} PRIVATE ${sample_library}) +target_link_libraries(${bindings_library} PRIVATE ${pyside2_link}) + +set_property(TARGET ${bindings_library} PROPERTY PREFIX "") +set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME + "${bindings_library}${PYTHON_EXTENSION_SUFFIX}") + +install(TARGETS ${bindings_library} ${sample_library} + LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} + RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} + ) diff --git a/kcardgame/binding-example/LICENSE b/kcardgame/binding-example/LICENSE new file mode 100644 index 00000000..6ca207ef --- /dev/null +++ b/kcardgame/binding-example/LICENSE @@ -0,0 +1,122 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + diff --git a/kcardgame/binding-example/bindings.h b/kcardgame/binding-example/bindings.h new file mode 100644 index 00000000..0629afe0 --- /dev/null +++ b/kcardgame/binding-example/bindings.h @@ -0,0 +1,3 @@ +#define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a))) + +#include "qobjectwithenum.h" diff --git a/kcardgame/binding-example/bindings.xml b/kcardgame/binding-example/bindings.xml new file mode 100644 index 00000000..29e009aa --- /dev/null +++ b/kcardgame/binding-example/bindings.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/kcardgame/binding-example/main.py b/kcardgame/binding-example/main.py new file mode 100644 index 00000000..a45bfa29 --- /dev/null +++ b/kcardgame/binding-example/main.py @@ -0,0 +1,7 @@ +from Shiboken2QtExample import * + +a = QObjectWithEnum() +a.someSignal.connect(lambda x: print("Signal emitted: %s" % x)) +a.aSlot() +print("int(QObjectWithEnum.MyEnum.Values) =", int(QObjectWithEnum.MyEnum.Values)) +a.nonSlotFunction(QObjectWithEnum.MyEnum.Some) diff --git a/kcardgame/binding-example/qobjectwithenum.cpp b/kcardgame/binding-example/qobjectwithenum.cpp new file mode 100644 index 00000000..5201e166 --- /dev/null +++ b/kcardgame/binding-example/qobjectwithenum.cpp @@ -0,0 +1,19 @@ +#include "qobjectwithenum.h" + +#include +#include + +QObjectWithEnum::QObjectWithEnum(QObject *parent) : QObject(parent) +{ +} + +QString QObjectWithEnum::nonSlotFunction(const QObjectWithEnum::MyEnum value) const { + const auto ret = metaObject()->enumerator(0).valueToKey(int(value)); + qDebug() << __FUNCTION__ << "returning:" << ret; + return ret; +} + +void QObjectWithEnum::aSlot() { + qDebug() << __FUNCTION__ << "slot called"; + emit someSignal("from aSlot"); +} diff --git a/kcardgame/binding-example/qobjectwithenum.h b/kcardgame/binding-example/qobjectwithenum.h new file mode 100644 index 00000000..353f03f6 --- /dev/null +++ b/kcardgame/binding-example/qobjectwithenum.h @@ -0,0 +1,28 @@ +#pragma once +#include + +class QObjectWithEnum : public QObject +{ + Q_OBJECT +public: + + enum class MyEnum { + Some, + Values, + For, + The, + Enum, + }; + Q_ENUM(MyEnum) + + explicit QObjectWithEnum(QObject *parent = nullptr); + + QString nonSlotFunction(const MyEnum value) const; + + +signals: + void someSignal(QString stringArg); + +public slots: + void aSlot(); +}; diff --git a/kcardgame/kcardgame.cpp b/kcardgame/kcardgame.cpp index 3cd45448..546806b0 100644 --- a/kcardgame/kcardgame.cpp +++ b/kcardgame/kcardgame.cpp @@ -3,6 +3,8 @@ #include "Python.h" #include "arrayobject.h" #include "kcardgame.hpp" +#include +#include "QtGui/pyside2_qtgui_python.h" #include /* #### Globals #################################### */ @@ -60,6 +62,18 @@ static PyObject *np_kcardgame(PyObject *self, PyObject *args) auto ret = new KCardDeck( KCardTheme(), nullptr); return PyCapsule_New(ret, "KCardDeck", del_kcardgame); } +static PyObject *get_card_pixmap(PyObject *self, PyObject *args) +{ + PyObject * kcard; + int i; + if (! PyArg_ParseTuple(args, "Oi", &kcard, &i)) + { + return NULL; + } + auto deck = (KCardDeck *)PyCapsule_GetPointer(kcard, "KCardDeck"); + auto ret = new QPixmap(deck->cardPixmap(i, true)); + return PyType_GenericNew(Shiboken::SbkType, ret, NULL); +} /* ==== Square vector components & multiply by a float ========================= /* #### Vector Utility functions ######################### */ diff --git a/kcardgame/minbool_test.py b/kcardgame/minbool_test.py new file mode 100644 index 00000000..020e9a41 --- /dev/null +++ b/kcardgame/minbool_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of Qt for Python. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from minimal import MinBoolUser + +class DerivedMinBoolUser (MinBoolUser): + def returnMyselfVirtual(self): + return MinBoolUser() + +class MinBoolTest(unittest.TestCase): + + def testMinBoolUser(self): + mbuTrue = MinBoolUser() + mbuFalse = MinBoolUser() + mbuTrue.setMinBool(True) + self.assertEqual(mbuFalse.minBool(), False) + self.assertEqual(mbuTrue.minBool(), True) + self.assertEqual(mbuTrue.callInvertedMinBool(), False) + + self.assertEqual(mbuTrue.minBool() == True, True) + self.assertEqual(False == mbuFalse.minBool(), True) + self.assertEqual(mbuTrue.minBool() == mbuFalse.minBool(), False) + + self.assertEqual(mbuFalse.minBool() != True, True) + self.assertEqual(True != mbuFalse.minBool(), True) + self.assertEqual(mbuTrue.minBool() != mbuFalse.minBool(), True) + + def testVirtuals(self): + dmbu = DerivedMinBoolUser() + self.assertEqual(dmbu.invertedMinBool(), True) + +if __name__ == '__main__': + unittest.main() + diff --git a/kcardgame/minimal-binding.txt.in b/kcardgame/minimal-binding.txt.in new file mode 100644 index 00000000..85b13967 --- /dev/null +++ b/kcardgame/minimal-binding.txt.in @@ -0,0 +1,15 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @minimal_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libminimal_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +enable-parent-ctor-heuristic +use-isnull-as-nb_nonzero diff --git a/kcardgame/typesystem_minimal.xml b/kcardgame/typesystem_minimal.xml new file mode 100644 index 00000000..968b27c5 --- /dev/null +++ b/kcardgame/typesystem_minimal.xml @@ -0,0 +1,93 @@ + + + + + + + + + + return PyBool_FromLong(%in.value()); + + + + %out = %OUTTYPE(%in == Py_True); + + + + + + + + + + PyObject* %out = PyList_New((int) %in.size()); + %INTYPE::const_iterator it = %in.begin(); + for (int idx = 0; it != %in.end(); ++it, ++idx) { + %INTYPE_0 cppItem(*it); + PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); + } + return %out; + + + + Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq.object()); i++) { + PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), i); + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + %out.push_back(cppItem); + } + + + + + + + + + + + + + + + + + %INTYPE::size_type vectorSize = %in.size(); + PyObject* %out = PyList_New((int) vectorSize); + for (%INTYPE::size_type idx = 0; idx < vectorSize; ++idx) { + %INTYPE_0 cppItem(%in[idx]); + PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); + } + return %out; + + + + Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); + int vectorSize = PySequence_Fast_GET_SIZE(seq.object()); + %out.reserve(vectorSize); + for (int idx = 0; idx < vectorSize; ++idx ) { + PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), idx); + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + %out.push_back(cppItem); + } + + + + + + + + + + + + + + + + + + + +