Skip to content

[3pt] Passing an integer or double parameter to a C stored function #2327

Open
@msiomkin

Description

@msiomkin

Feature name

subj

Product: Tarantool
Since: 1.x
Audience/target: developers
Root document: https://www.tarantool.io/en/doc/latest/tutorials/c_tutorial/#f-c-tutorial-harder
SME: @ ImeevMA, @ msiomkin

Details

There is an example of passing an unsigned integer parameter to a C stored function. Everything is OK with it but it's the most trivial case. Much more interesting is passing a signed integer parameter. How do I it? I.e. how do I extract the passed value in a function? May be I shall just call mp_decode_int? No, it doesn't work (at least for positive numbers). It returns trash in the release version and triggers an assertion in the debug version of Tarantool. Ok, may be I can decode the number as unsigned int (calling mp_decode_uint) and then cast it to int? No, it doesn't work either (at least for negative numbers): the behaviour is similar to the previous one. Oh, I think I got it: probably I need to explicitly define the parameter type in metadata. Something like this:

    box.schema.func.create('harder', {
        language = 'C',
        param_list = { "integer", "integer", "integer") -- if I know how many params I will have...
    }
)

No, it doesn't have any effect. What on earth shall I do? See the source code of course...

MP_IMPL char *
mp_encode_int(char *data, int64_t num)
{
	assert(num < 0);
        ...

Oh yes, our Message Pack library uses int value representation only to encode negative numbers. And due to message pack type markers we can't decode unsigned int as int and vice versa. It looks like an extreme optimization strategy that bursts a layman's brain out. But how can I know inside a function what value will I get in an integer parameter? Positive or negative? I need to analyse the type markers of course. Ok, do I need to write a wrapper function for it then? No, the authors of msgpuck library kindly did it for us:

MP_PROTO int
mp_read_int32(const char **data, int32_t *ret);

MP_PROTO int
mp_read_int64(const char **data, int64_t *ret);

And, yes, things are even more exciting for a double parameter. You may easily end up with getting an unsigned or signed integer or a floating point number as its value. So, please, use:

MP_PROTO int
mp_read_double(const char **data, double *ret);

It's a history of long suffering in fact. The described things are not obvious at all (int = negative number? ehm..., what?). I think we should give an exhaustive example to clear things up and prevent the following hurts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    add details[nature] More details needed, some info missing. Documentation is incomplete.exampleProblem with a code example.rewrite[nature] Revise existing text for structure/phrasing/termstutorial[area] Related to Tutorials

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions