0

I'm am creating PHP extension using PHP library, and I am having difficulties converting C++ map variable to PHPCPP Php::Value returned by a function. The reason I'm doing this is to get multidimensional associative array result from a function written in C++.

Is there a way to convert C++ map < string, map < double, map < double, map< double, map< string, map< int, double>>>>>> data to Php::Value in PHPCPP, or is there a better way of dealing with this?

Here is my C++ code:

#include <phpcpp.h>
#include <ctime>
#include <iostream>
#include <map>
#include <algorithm>
#include <string> 
#include <regex>
#include <stdlib.h>     /* atof,strtod */
#include <cstddef>        // std::size_t
#include <sstream>
#include <vector>
#include <boost/algorithm/string.hpp> // include Boost, a C++ library
#include <boost/regex.hpp>
using namespace std;



double get_curve_rate(string curve_type, double shape, double peak, double tpeak, double lag, string start, string index, double interval) {

    double rate = 0.0;
    if (curve_type == "t1") {
        if ((shape + peak + tpeak) != 0)
            rate = 0;

    }
    else if (curve_type == "t2") {
        if ((peak + tpeak + lag) != 0)
            rate = 1;
    }
    return  rate;
}
class Curve : public Php::Base
{
public :
    string type;
    double shape = 0.0;
    double peak = 0.0;
    double tpeak = 0.0;
    double lag = 0.0;
    string start;
    double interval = 0.0;
    int month_no = 0;
    string month;
    string start_date;
        /**
        *  C++ constructor and destructor
        */
        Curve() {}
        virtual ~Curve() {}


};

Php::Value get_all_curve_rates(Php::Parameters &params) {

    vector<Curve> curves = params[0];
    //create an associative array and return to php
    map< string, map<double, map<double, map<double, map<string, map<int, double>>>>>> data;

    for (auto &c : curves) // access by reference to avoid copying
    {
        if (c.type == "t1"){}
    //      data[c.type][c.peak][c.tpeak][c.lag][c.start_date][c.month_no] = get_curve_rate(c.type, c.shape, c.peak, c.tpeak, c.lag, c.start, c.month, c.interval);
        else if (c.type == "t2") {}
    //      data[c.type][c.shape][c.peak][c.tpeak][c.start_date][c.month_no] = get_curve_rate(c.type, c.shape, c.peak, c.tpeak, c.lag, c.start, c.month, c.interval);

    }


    return data;
}

/**
*  Switch to C context, because the Zend engine expects get get_module()
*  to have a C style function signature
*/
extern "C" {
    /**
    *  Startup function that is automatically called by the Zend engine
    *  when PHP starts, and that should return the extension details
    *  @return void*
    */
    PHPCPP_EXPORT void *get_module()
    {
        // the extension object
        static Php::Extension extension("test", "1.0");

        // add functions so that they can be called from PHP scripts

        // description of the class so that PHP knows which methods are accessible
        Php::Class<Curve> curve("Curve");


        extension.add("get_all_curve_rates", get_all_curve_rates, {
            Php::ByVal("curves", Php::Type::Array),
        });
        // return the extension details
        return extension;
    }
} 

Compiler gives these errors:

In file included from /usr/include/phpcpp.h:42:0,
                 from main.cpp:1:
/usr/include/phpcpp/value.h: In instantiation of ‘Php::Value::Value(const std::map<std::basic_string<char>, T>&) [with T = std::map<double, std::map<double, std::map<double, std::map<std::basic_string<char>, std::map<int, double> > > > >]’:
main.cpp:428:9:   required from here
/usr/include/phpcpp/value.h:113:34: error: no matching function for call to ‘Php::Value::setRaw(const char*, std::basic_string<char>::size_type, const std::map<double, std::map<double, std::map<double, std::map<std::basic_string<char>, std::map<int, double> > > > >&)’
         for (auto &iter : value) setRaw(iter.first.c_str(), iter.first.size(), iter.second);
                                  ^~~~~~
In file included from /usr/include/phpcpp.h:42:0,
                 from main.cpp:1:
/usr/include/phpcpp/value.h:1165:10: note: candidate: void Php::Value::setRaw(int, const Php::Value&)
     void setRaw(int index, const Value &value);
          ^~~~~~
/usr/include/phpcpp/value.h:1165:10: note:   candidate expects 2 arguments, 3 provided
/usr/include/phpcpp/value.h:1176:10: note: candidate: void Php::Value::setRaw(const char*, int, const Php::Value&)
     void setRaw(const char *key, int size, const Value &value);
          ^~~~~~
/usr/include/phpcpp/value.h:1176:10: note:   no known conversion for argument 3 from ‘const std::map<double, std::map<double, std::map<double, std::map<std::basic_string<char>, std::map<int, double> > > > >’ to ‘const Php::Value&’
In file included from /usr/include/phpcpp.h:42:0,
                 from main.cpp:1:
/usr/include/phpcpp/value.h: In instantiation of ‘std::vector<T> Php::Value::vectorValue() const [with T = Curve]’:
/usr/include/phpcpp/value.h:723:30:   required from ‘Php::Value::operator std::vector<T>() const [with T = Curve]’
main.cpp:414:33:   required from here
/usr/include/phpcpp/value.h:483:13: error: no matching function for call to ‘std::vector<Curve>::push_back(Php::Value)’
             result.push_back(get(i));
             ^~~~~~
In file included from /opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/vector:64:0,
                 from /usr/include/phpcpp.h:19,
                 from main.cpp:1:
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Curve; _Alloc = std::allocator<Curve>; std::vector<_Tp, _Alloc>::value_type = Curve]
       push_back(const value_type& __x)
       ^~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from ‘Php::Value’ to ‘const value_type& {aka const Curve&}’
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Curve; _Alloc = std::allocator<Curve>; std::vector<_Tp, _Alloc>::value_type = Curve]
       push_back(value_type&& __x)
       ^~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from ‘Php::Value’ to ‘std::vector<Curve>::value_type&& {aka Curve&&}’
make: *** [main.o] Error 1

Any suggestions how to fix these errors?

UPDATE Have tried implementing an example Caleth suggested below by modifying C++ :

  class Curve : public Php::Base
    {
    public :
        string type;
        double shape = 0.0;
        double peak = 0.0;
        double tpeak = 0.0;
        double lag = 0.0;
        string start;
        double interval = 0.0;
        int month_no = 0;
        string month;
        string start_date;
            /**
            *  C++ constructor and destructor
            */
            //Curve() {}
            //virtual ~Curve() {}
        Curve(Php::Value value) :
            type(value["type"]),
            shape(value["shape"]),
            peak(value["peak"]),
            tpeak(value["tpeak"]),
            lag(value["lag"]),
            interval(value["interval"]),
            month_no(value["month_no"]),
            month(value["month"]),
            start_date(value["start_date"])
        {}

                operator Php::Value() const
            {
                Php::Value value;
                value["type"] = type;
                value["shape"] = shape;
                value["peak"] = peak;
                value["tpeak"] = tpeak;
                value["lag"] = lag;
                value["interval"] = interval;
                value["month_no"] = month_no;
                value["month"] = month;
                value["start_date"] = start_date;

                return value;
            }

    };


    Php::Value get_all_curve_rates(Php::Parameters &params) {

        vector<Php::Value> curves = params[0];

        Php::Value data;

        for (auto &c : curves) // access by reference to avoid copying
        {
            Curve curv = c;
            if (curv.type == "t1")
                data[curv.type][curv.peak][curv.tpeak][curv.lag][curv.start_date][curv.month_no] = 2.0;//get_curve_rate(curv.type, curv.shape, curv.peak, curv.tpeak, curv.lag, curv.start, curv.month, curv.interval);
            else if (curv.type == "t2")
                data[curv.type][curv.shape][curv.peak][curv.tpeak][curv.start_date][curv.month_no] = 1.0;//get_curve_rate(curv.type, curv.shape, curv.peak, curv.tpeak, curv.lag, curv.start, curv.month, curv.interval);

        }


        return data;
    }
/**
*  Switch to C context, because the Zend engine expects get get_module()
*  to have a C style function signature
*/
extern "C" {
    /**
    *  Startup function that is automatically called by the Zend engine
    *  when PHP starts, and that should return the extension details
    *  @return void*
    */
    PHPCPP_EXPORT void *get_module()
    {
        // the extension object
        static Php::Extension extension("test", "1.0");

        // add functions so that they can be called from PHP scripts

        // description of the class so that PHP knows which methods are accessible
        Php::Class<Curve> curve("Curve");

        extension.add("get_all_curve_rates", get_all_curve_rates, {
            Php::ByVal("Curve", Php::Type::Array),
        });
        // return the extension details
        return extension;
    }
}

However now there are other error:

/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:3010:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^~~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:2975:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const basic_string& __str);
       ^~~~~~~~~~~~
main.cpp:417:33: error: call of overloaded ‘basic_string(Php::HashMember<std::basic_string<char> >)’ is ambiguous
   start_date(value["start_date"])
                                 ^
In file included from /opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/string:52:0,
                 from /usr/include/phpcpp.h:17,
                 from main.cpp:1:
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:3027:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(basic_string&& __str)
       ^~~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:3010:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^~~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:2975:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const basic_string& __str);
       ^~~~~~~~~~~~
main.cpp:417:33: error: call of overloaded ‘basic_string(Php::HashMember<std::basic_string<char> >)’ is ambiguous
   start_date(value["start_date"])
                                 ^
In file included from /opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/string:52:0,
                 from /usr/include/phpcpp.h:17,
                 from main.cpp:1:
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:3027:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(basic_string&& __str)
       ^~~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:3010:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^~~~~~~~~~~~
/opt/rh/devtoolset-6/root/usr/include/c++/6.2.1/bits/basic_string.h:2975:7: note: candidate: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const basic_string& __str);
       ^~~~~~~~~~~~
make: *** [main.o] Error 1
6
  • What happens when you declare data as Php::Value data;? Does Php::Value::operator[] exist for all those types? Commented Aug 10, 2017 at 13:06
  • Aside: I really don't want to be on the receiving end of a 6 deep map. Why not a map<Curve, double>? Commented Aug 10, 2017 at 13:08
  • i have found it easier to access multidimensional associative array $data[$x1][$x2][$y1][$y2][$z1][$z2] value within loops in PHP otherwise i would need to loop through map<Curve, double> all objects to find a specific value for specific set of parameters or is there a quick way to get a value from array of objects? Commented Aug 10, 2017 at 13:42
  • what about '$data[Curve($x1, $x2, $y1, $y2, $z1, $z2)]'? Or does PHP force maps to use object identity and not value? In which case I'd look for a PHP equivalent of python's NamedTuple Commented Aug 10, 2017 at 13:45
  • Also, why not just write all this in PHP? You are writing some seriously un-idiomatic c++. It will not be "fast". It will not be maintainable Commented Aug 10, 2017 at 14:00

1 Answer 1

0

You need to provide a way of converting Php::Values into Curves. Looking at the docs, this is generally done in class.

class Curve : public Php::Base
{
public :
    string type;
    double shape = 0.0;
    double peak = 0.0;
    double tpeak = 0.0;
    double lag = 0.0;
    string start;
    double interval = 0.0;
    int month_no = 0;
    string month;
    string start_date;

    Curve(Php::Value value)
      : type(value["type"]), 
        shape(value["shape"]),
        // etc... 
        {}

    operator Php::Value() const 
    {
        Php::Value value;
        value["type"] = type;
        value["shape"] = shape;
        // etc...
        return value;
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Have just tried this and compiler give this error: main.cpp: In function ‘Php::Value get_all_curve_rates(Php::Parameters&)’: main.cpp:421:16: error: conversion from ‘Php::Value’ to non-scalar type ‘Curve’ requested Curve curv = c;
Is the "Curve" in Php::Class<Curve> curve("Curve"); meant to relate to the "curves" in Php::ByVal("curves", Php::Type::Array)? They are spelled differently
ByVal("curves", Php::Type::Array) - "curves" is just a name of a parameter, however i have updated to "Curve" and still get the same error:main.cpp: In function ‘Php::Value get_all_curve_rates(Php::Parameters&)’: main.cpp:421:16: error: conversion from ‘Php::Value’ to non-scalar type ‘Curve’ requested Curve curv = c;
Ok, I've looked things up, and you need to provide code to make Curves from Php::Values. That's what the error messages are.
Where did you find that? does it say how to declare Php::Value when it is an array of objects so PHPCPP would understand that?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.