Using SWIG to wrap a class member function that returns std::tuple

I’m attempting to wrap a class using swig. The class has a member function called readKeyword that returns a std::tuple< std::uint32_t,std::int32_t,std::uint64_t,std::int64_t,double,std::string >.

There seems to be a type-mismatch between what readkeyword is returning and the SwigValueWrapper instance that the return is being stored into.

Here’s some info about the class I’m trying to wrap.

//CArcFitsFile.h

...

#include <string>
 
#ifdef __cpp_lib_variant
    #include <variant>
#else
    #include <tuple>
#endif

...

namespace arc
{
    namespace gen3
    {
 
        namespace fits
        {
 
            using BPP_16 = std::uint16_t;
 
            using BPP_32 = std::uint32_t;
 
 
            #ifdef __cpp_lib_variant
                using keywordValue_t = std::variant<std::uint32_t, std::int32_t, std::uint64_t, std::int64_t, double, std::string>;
            #else
                using keywordValue_t = std::tuple<std::uint32_t, std::int32_t, std::uint64_t, std::int64_t, double, std::string>;
            #endif

...

        template <typename T = arc::gen3::fits::BPP_16>
        class GEN3_CARCFITSFILE_API CArcFitsFile : public arc::gen3::CArcBase
        {
            public:
 
                CArcFitsFile( void );
 
                virtual ~CArcFitsFile( void );
...
                arc::gen3::fits::keywordValue_t readKeyword( const std::string& sKey, arc::gen3::fits::e_Type eType );
...

Here’s my interface file

//ArcFits.i

%define ModuleDocStr
"Python interface to CArcDeinterlace C++ code."
%enddef

%feature("autodoc", "1");
%module(package="ArcLib", docstring=ModuleDocStr) ArcFitsFile

%{
#include <filesystem>
#include <version>
#include <stdexcept>
#include <cstdint>
#include <utility>
#include <memory>
#include <string>

#include <tuple>

#include <CArcFitsFileDllMain.h>
#include <CArcStringList.h>
#include <CArcBase.h>
#include <fitsio.h>
#include <CArcFitsFile.h>
%}

%init %{
%}

#define __attribute__(x)
#define GEN3_CARCFITSFILE_API __attribute__((visibility("default")))

// Specifies the default C++ to python exception handling interface
%exception {
    try {
        $action
    } catch (std::domain_error & e) {
        PyErr_SetString(PyExc_ArithmeticError, e.what());
        SWIG_fail;
    } catch (std::invalid_argument & e) {
        PyErr_SetString(PyExc_ValueError, e.what());
        SWIG_fail;
    } catch (std::length_error & e) {
        PyErr_SetString(PyExc_IndexError, e.what());
        SWIG_fail;
    } catch (std::out_of_range & e) {
        PyErr_SetString(PyExc_ValueError, e.what());
        SWIG_fail;
    } catch (std::logic_error & e) {
        PyErr_SetString(PyExc_RuntimeError, e.what());
        SWIG_fail;
    } catch (std::range_error & e) {
        PyErr_SetString(PyExc_ValueError, e.what());
        SWIG_fail;
    } catch (std::underflow_error & e) {
        PyErr_SetString(PyExc_ArithmeticError, e.what());
        SWIG_fail;
    } catch (std::overflow_error & e) {
        PyErr_SetString(PyExc_OverflowError, e.what());
        SWIG_fail;
    } catch (std::runtime_error & e) {
        PyErr_SetString(PyExc_RuntimeError, e.what());
        SWIG_fail;
    } catch (std::exception & e) {
        PyErr_SetString(PyExc_Exception, e.what());
        SWIG_fail;
    } catch (...) {
        SWIG_fail;
    }
}
%include "std_unique_ptr.i"
%include "typemaps.i"
%include "std_string.i"
%include "CArcFitsFile.h"

//%template(arcDeinterlaceUint8) arc::gen3::CArcDeinterlace<uint8_t>;
%template(arcFitsFileUint16) arc::gen3::CArcFitsFile<arc::gen3::fits::BPP_16>;
%template(arcFitsFileUint32) arc::gen3::CArcFitsFile<arc::gen3::fits::BPP_32>;

When the compiler compiles the generated wrapper code, I get a compiler error in both the arcFitsFileUint16 and arcFitsFileUint32 templates for the readKeyword member function:

running build_ext
building '_ArcFitsFile' extension
swigging ArcLib/ArcFitsFile.i to ArcLib/ArcFitsFile_wrap.cpp
swig -python -Isrc/ARC_API/3.6.2/CArcDeinterlace/inc -Isrc/ARC_API/3.6.2/CArcImage/inc -Isrc/ARC_API/3.6.2/CArcFitsFile/inc -Isrc/ARC_API/3.6.2/CArcAPIClient/inc -Isrc/ARC_API/3.6.2/CArcDisplay/inc -Isrc/ARC_API/3.6.2/CArcBase/inc -Isrc/ARC_API/3.6.2/CArcDevice/inc -Isrc/ARC_API/3.6.2/cfitsio-3450/include -Iinclude -Iinclude -c++ -Wall -o ArcLib/ArcFitsFile_wrap.cpp ArcLib/ArcFitsFile.i
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:206: Warning 345: Unable to deduce auto return type for 'MAKE_POINT(std::uint32_t,std::uint32_t)' (ignored).
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:522: Warning 317: Specialization of non-template 'default_delete'.
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:269: Warning 321: 'open' conflicts with a built-in name in python
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:269: Warning 321: 'open' conflicts with a built-in name in python
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:269: Warning 321: 'open' conflicts with a built-in name in python
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:269: Warning 321: 'open' conflicts with a built-in name in python
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:216: Warning 401: Nothing known about base class 'arc::gen3::CArcBase'. Ignored.
src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:216: Warning 401: Nothing known about base class 'arc::gen3::CArcBase'. Ignored.
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -Isrc/ARC_API/3.6.2/CArcDeinterlace/inc -Isrc/ARC_API/3.6.2/CArcImage/inc -Isrc/ARC_API/3.6.2/CArcFitsFile/inc -Isrc/ARC_API/3.6.2/CArcAPIClient/inc -Isrc/ARC_API/3.6.2/CArcDisplay/inc -Isrc/ARC_API/3.6.2/CArcBase/inc -Isrc/ARC_API/3.6.2/CArcDevice/inc -Isrc/ARC_API/3.6.2/cfitsio-3450/include -Iinclude -I/usr/include/python3.10 -c ArcLib/ArcFitsFile_wrap.cpp -o build/temp.linux-x86_64-cpython-310/ArcLib/ArcFitsFile_wrap.o -std=c++20
ArcLib/ArcFitsFile_wrap.cpp: In function ‘PyObject* _wrap_arcFitsFileUint16_readKeyword(PyObject*, PyObject*)’:
ArcLib/ArcFitsFile_wrap.cpp:5306:67: error: no match for ‘operator=’ (operand types are ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ and ‘arc::gen3::fits::keywordValue_t’ {aka ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >’})
 5306 |       result = (arg1)->readKeyword((std::string const &)*arg2,arg3);
      |                                                                   ^
ArcLib/ArcFitsFile_wrap.cpp:3209:21: note: candidate: ‘SwigValueWrapper<T>& SwigValueWrapper<T>::operator=(const SwigValueWrapper<T>&) [with T = std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >]’
 3209 |   SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
      |                     ^~~~~~~~
ArcLib/ArcFitsFile_wrap.cpp:3209:58: note:   no known conversion for argument 1 from ‘arc::gen3::fits::keywordValue_t’ {aka ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >’} to ‘const SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&’
 3209 |   SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
      |                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
ArcLib/ArcFitsFile_wrap.cpp:3213:21: note: candidate: ‘SwigValueWrapper<T>& SwigValueWrapper<T>::operator=(const T&) [with T = std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >]’
 3213 |   SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; }
      |                     ^~~~~~~~
ArcLib/ArcFitsFile_wrap.cpp:3213:40: note:   no known conversion for argument 1 from ‘arc::gen3::fits::keywordValue_t’ {aka ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >’} to ‘const std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&’
 3213 |   SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; }
      |                               ~~~~~~~~~^
ArcLib/ArcFitsFile_wrap.cpp:3215:21: note: candidate: ‘SwigValueWrapper<T>& SwigValueWrapper<T>::operator=(T&&) [with T = std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >]’
 3215 |   SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; }
      |                     ^~~~~~~~
ArcLib/ArcFitsFile_wrap.cpp:3215:35: note:   no known conversion for argument 1 from ‘arc::gen3::fits::keywordValue_t’ {aka ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >’} to ‘std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&&’
 3215 |   SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; }
      |                               ~~~~^
ArcLib/ArcFitsFile_wrap.cpp:5341:77: error: no matching function for call to ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::variant(SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)’
 5341 |   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__int32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
      |                                                                             ^
ArcLib/ArcFitsFile_wrap.cpp:1140:89: note: in definition of macro ‘SWIG_NewPointerObj’
 1140 | #define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
      |                                                                                         ^~~
In file included from src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:27,
                 from ArcLib/ArcFitsFile_wrap.cpp:3337:
/usr/include/c++/11/variant:1450:9: note: candidate: ‘template<long unsigned int _Np, class _Up, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, std::initializer_list<_Up>, _Args&& ...) [with long unsigned int _Np = _Np; _Up = _Up; _Args = {_Args ...}; _Tp = _Tp; <template-parameter-2-5> = <template-parameter-1-5>; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1450 |         variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
      |         ^~~~~~~
/usr/include/c++/11/variant:1450:9: note:   template argument deduction/substitution failed:
ArcLib/ArcFitsFile_wrap.cpp:5341:77: note:   ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ is not derived from ‘std::in_place_index_t<_Idx>’
 5341 |   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__int32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
      |                                                                             ^
ArcLib/ArcFitsFile_wrap.cpp:1140:89: note: in definition of macro ‘SWIG_NewPointerObj’
 1140 | #define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
      |                                                                                         ^~~
In file included from src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:27,
                 from ArcLib/ArcFitsFile_wrap.cpp:3337:
/usr/include/c++/11/variant:1439:9: note: candidate: ‘template<long unsigned int _Np, class ... _Args, class _Tp, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, _Args&& ...) [with long unsigned int _Np = _Np; _Args = {_Args ...}; _Tp = _Tp; <template-parameter-2-4> = <template-parameter-1-4>; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1439 |         variant(in_place_index_t<_Np>, _Args&&... __args)
      |         ^~~~~~~
/usr/include/c++/11/variant:1439:9: note:   template argument deduction/substitution failed:
ArcLib/ArcFitsFile_wrap.cpp:5341:77: note:   ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ is not derived from ‘std::in_place_index_t<_Idx>’
 5341 |   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__int32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
      |                                                                             ^
ArcLib/ArcFitsFile_wrap.cpp:1140:89: note: in definition of macro ‘SWIG_NewPointerObj’
 1140 | #define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
      |                                                                                         ^~~
In file included from src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:27,
                 from ArcLib/ArcFitsFile_wrap.cpp:3337:
/usr/include/c++/11/variant:1429:9: note: candidate: ‘template<class _Tp, class _Up, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, std::initializer_list<_Up>, _Args&& ...) [with _Tp = _Tp; _Up = _Up; _Args = {_Args ...}; <template-parameter-2-4> = <template-parameter-1-4>; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1429 |         variant(in_place_type_t<_Tp>, initializer_list<_Up> __il,
      |         ^~~~~~~
/usr/include/c++/11/variant:1429:9: note:   template argument deduction/substitution failed:
ArcLib/ArcFitsFile_wrap.cpp:5341:77: note:   ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ is not derived from ‘std::in_place_type_t<_Tp>’
 5341 |   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__int32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
      |                                                                             ^
ArcLib/ArcFitsFile_wrap.cpp:1140:89: note: in definition of macro ‘SWIG_NewPointerObj’
 1140 | #define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
      |                                                                                         ^~~
In file included from src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:27,
                 from ArcLib/ArcFitsFile_wrap.cpp:3337:
/usr/include/c++/11/variant:1419:9: note: candidate: ‘template<class _Tp, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_type_t<_Tp>, _Args&& ...) [with _Tp = _Tp; _Args = {_Args ...}; <template-parameter-2-3> = <template-parameter-1-3>; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1419 |         variant(in_place_type_t<_Tp>, _Args&&... __args)
      |         ^~~~~~~
/usr/include/c++/11/variant:1419:9: note:   template argument deduction/substitution failed:
ArcLib/ArcFitsFile_wrap.cpp:5341:77: note:   ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ is not derived from ‘std::in_place_type_t<_Tp>’
 5341 |   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__int32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
      |                                                                             ^
ArcLib/ArcFitsFile_wrap.cpp:1140:89: note: in definition of macro ‘SWIG_NewPointerObj’
 1140 | #define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
      |                                                                                         ^~~
In file included from src/ARC_API/3.6.2/CArcFitsFile/inc/CArcFitsFile.h:27,
                 from ArcLib/ArcFitsFile_wrap.cpp:3337:
/usr/include/c++/11/variant:1409:9: note: candidate: ‘template<class _Tp, class, class, class _Tj, class> constexpr std::variant<_Types>::variant(_Tp&&) [with _Tp = _Tp; <template-parameter-2-2> = <template-parameter-1-2>; <template-parameter-2-3> = <template-parameter-1-3>; _Tj = _Tj; <template-parameter-2-5> = <template-parameter-1-5>; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1409 |         variant(_Tp&& __t)
      |         ^~~~~~~
/usr/include/c++/11/variant:1409:9: note:   template argument deduction/substitution failed:
/usr/include/c++/11/variant: In substitution of ‘template<class ... _Types> template<class _Tp, class> using __accepted_type = std::variant<_Types>::__to_type<__accepted_index<_Tp> > [with _Tp = SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&; <template-parameter-2-2> = void; _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’:
/usr/include/c++/11/variant:1405:9:   required from here
/usr/include/c++/11/variant:1375:15: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
 1375 |         using __accepted_type = __to_type<__accepted_index<_Tp>>;
      |               ^~~~~~~~~~~~~~~
/usr/include/c++/11/variant:1397:7: note: candidate: ‘std::variant<_Types>::variant(std::variant<_Types>&&) [with _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1397 |       variant(variant&&) = default;
      |       ^~~~~~~
/usr/include/c++/11/variant:1397:15: note:   no known conversion for argument 1 from ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ to ‘std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&&’
 1397 |       variant(variant&&) = default;
      |               ^~~~~~~~~
/usr/include/c++/11/variant:1396:7: note: candidate: ‘std::variant<_Types>::variant(const std::variant<_Types>&) [with _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1396 |       variant(const variant& __rhs) = default;
      |       ^~~~~~~
/usr/include/c++/11/variant:1396:30: note:   no known conversion for argument 1 from ‘SwigValueWrapper<std::tuple<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ to ‘const std::variant<unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&’
 1396 |       variant(const variant& __rhs) = default;
      |               ~~~~~~~~~~~~~~~^~~~~
/usr/include/c++/11/variant:1395:7: note: candidate: ‘constexpr std::variant<_Types>::variant() [with _Types = {unsigned int, int, long unsigned int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’
 1395 |       variant() = default;
      |       ^~~~~~~

…. and similar for ‘PyObject* _wrap_arcFitsFileUint32_readKeyword.

And here’s the generated wrapper code (included line numbers just for the heck of it):

 5268 SWIGINTERN PyObject *_wrap_arcFitsFileUint16_readKeyword(PyObject *self, PyObject *args) {
 5269   PyObject *resultobj = 0;
 5270   arc::gen3::CArcFitsFile< arc::gen3::fits::BPP_16 > *arg1 = (arc::gen3::CArcFitsFile< arc::gen3::fits::BPP_16 > *) 0 ;
 5271   std::string *arg2 = 0 ;
 5272   arc::gen3::fits::e_Type arg3 ;
 5273   void *argp1 = 0 ;
 5274   int res1 = 0 ;
 5275   int res2 = SWIG_OLDOBJ ;
 5276   int val3 ;
 5277   int ecode3 = 0 ;
 5278   PyObject *swig_obj[3] ;
 5279   SwigValueWrapper< std::tuple< std::uint32_t,std::int32_t,std::uint64_t,std::int64_t,double,std::string > > result;
 5280 
 5281   (void)self;
 5282   if (!SWIG_Python_UnpackTuple(args, "arcFitsFileUint16_readKeyword", 3, 3, swig_obj)) SWIG_fail;
 5283   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_arc__gen3__CArcFitsFileT_arc__gen3__fits__BPP_16_t, 0 |  0 );
 5284   if (!SWIG_IsOK(res1)) {
 5285     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "arcFitsFileUint16_readKeyword" "', argument " "1"" of type '" "a      rc::gen3::CArcFitsFile< arc::gen3::fits::BPP_16 > *""'");
 5286   }
 5287   arg1 = reinterpret_cast< arc::gen3::CArcFitsFile< arc::gen3::fits::BPP_16 > * >(argp1);
 5288   {
 5289     std::string *ptr = (std::string *)0;
 5290     res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr);
 5291     if (!SWIG_IsOK(res2)) {
 5292       SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "arcFitsFileUint16_readKeyword" "', argument " "2"" of type '"       "std::string const &""'");
 5293     }
 5294     if (!ptr) {
 5295       SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "arcFitsFileUint16_readKeyword" "', argum      ent " "2"" of type '" "std::string const &""'");
 5296     }
 5297     arg2 = ptr;
 5298   }
 5299   ecode3 = SWIG_AsVal_int(swig_obj[2], &val3);
 5300   if (!SWIG_IsOK(ecode3)) {
 5301     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "arcFitsFileUint16_readKeyword" "', argument " "3"" of type '"       "arc::gen3::fits::e_Type""'");
 5302   }
 5303   arg3 = static_cast< arc::gen3::fits::e_Type >(val3);
 5304   {
 5305     try {
 5306       result = (arg1)->readKeyword((std::string const &)*arg2,arg3);
 5307     } catch (std::domain_error & e) {
 5308       PyErr_SetString(PyExc_ArithmeticError, e.what());
 5309       SWIG_fail;
 5310     } catch (std::invalid_argument & e) {
 5311       PyErr_SetString(PyExc_ValueError, e.what());
 5312       SWIG_fail;
 5313     } catch (std::length_error & e) {
 5314       PyErr_SetString(PyExc_IndexError, e.what());
 5315       SWIG_fail;
 5316     } catch (std::out_of_range & e) {
 5317       PyErr_SetString(PyExc_ValueError, e.what());
 5318       SWIG_fail;
 5319     } catch (std::logic_error & e) {
 5320       PyErr_SetString(PyExc_RuntimeError, e.what());
 5321       SWIG_fail;
 5322     } catch (std::range_error & e) {
 5323       PyErr_SetString(PyExc_ValueError, e.what());
 5324       SWIG_fail;
 5325     } catch (std::underflow_error & e) {
 5326       PyErr_SetString(PyExc_ArithmeticError, e.what());
 5327       SWIG_fail;
 5328     } catch (std::overflow_error & e) {
 5329       PyErr_SetString(PyExc_OverflowError, e.what());
 5330       SWIG_fail;
 5331     } catch (std::runtime_error & e) {
 5332       PyErr_SetString(PyExc_RuntimeError, e.what());
 5333       SWIG_fail;
 5334     } catch (std::exception & e) {
 5335       PyErr_SetString(PyExc_Exception, e.what());
 5336       SWIG_fail;
 5337     } catch (...) {
 5338       SWIG_fail;
 5339     }
 5340   }
 5341   resultobj = SWIG_NewPointerObj((new arc::gen3::fits::keywordValue_t(result)), SWIGTYPE_p_std__tupleT_std__uint32_t_std__in      t32_t_std__uint64_t_std__int64_t_double_std__string_t, SWIG_POINTER_OWN |  0 );
 5342   if (SWIG_IsNewObj(res2)) delete arg2;
 5343   return resultobj;
 5344 fail:
 5345   if (SWIG_IsNewObj(res2)) delete arg2;
 5346   return NULL;
 5347 }

These are the allowed operators for SwigValueWrapper (also from the generated wrapper code):

 3201 template<typename T> class SwigValueWrapper {
 3202   struct SwigSmartPointer {
 3203     T *ptr;
 3204     SwigSmartPointer(T *p) : ptr(p) { }
 3205     ~SwigSmartPointer() { delete ptr; }
 3206     SwigSmartPointer& operator=(SwigSmartPointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; r      eturn *this; }
 3207     void reset(T *p) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = p; }
 3208   } pointer;
 3209   SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
 3210   SwigValueWrapper(const SwigValueWrapper<T>& rhs);
 3211 public:
 3212   SwigValueWrapper() : pointer(0) { }
 3213   SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; }
 3214 #if __cplusplus >=201103L
 3215   SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; }
 3216   operator T&&() const { return std::move(*pointer.ptr); }
 3217 #else
 3218   operator T&() const { return *pointer.ptr; }
 3219 #endif
 3220   T *operator&() const { return pointer.ptr; }
 3221   static void reset(SwigValueWrapper& t, T *p) { t.pointer.reset(p); }
 3222 };

It seems to me the issue here is that result and the return value for readKeyword are type-mismatched, but why? And how might I go about getting them matched?

Maybe SWIG doesn’t play nicely with tuples? I’ve looked and there doesn’t seem to be an interface for std::tuple. But I would expect for _wrap_arcFitsFileUint16_readKeyword to return a std::tuple * at the very least.

I’m somewhat new to SWIG and am learning, but I don’t yet know all the ins and outs. Thanks.

UPDATE
This wasn’t a tuple issue at all. See my solution below.

I solved it. Somewhere during compilation the preprocessor was including <variant>.

I was using #include <tuple> in my interface file, so I had assumed __cpp_lib_variant would remain undefined while I was compiling the wrapper code.

Adding the following preprocessor directives to my interface file allowed my code to compile.

#ifdef __cpp_lib_variant
        #undef __cpp_lib_variant
#endif
#include <tuple>

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật