Can I call a function with pointers of different type?

F

fl

Hi,
I have a program which is originally from Matlab mex function. I would
like to rewrite it in order to run in plain C. The mex interface is a
Matlab standard. prhs is the call parameter pointer array. Some
pointers point to array while some point to integer. Matlab uses
different mxGetPr() to get pointer, or uses mxGetScalar() to get
value.

If I write the interface in general C, I try to define prhs as
pointer's point to integer. If I store some elements of plhs to
pointers while others to integer, the compiler gives warning. The
compiler wants prhs as the same level pointers. This kind of warning
is dangerous or not?

Another method I think is to use a structer to transfer data to the
function.

Do you have some good methods on my question? Thanks.

...................
int **plhs, **prhs;

prhs = ptr_arr;
mexFunction(nlhs, plhs, nrhs, prhs);
 
E

Eric Sosman

Hi,
I have a program which is originally from Matlab mex function. I would
like to rewrite it in order to run in plain C. The mex interface is a
Matlab standard. prhs is the call parameter pointer array. Some
pointers point to array while some point to integer. Matlab uses
different mxGetPr() to get pointer, or uses mxGetScalar() to get
value.

It is possible that a pointer points to an array, but it is
very unusual. Are you sure "point to array" is correct? Please
visit <http://www.c-faq.com/> and read Section 6, or at the very
least Questions 6.12 and 6.13, and then try again to describe
exactly what you're doing.
If I write the interface in general C, I try to define prhs as
pointer's point to integer. If I store some elements of plhs to
pointers while others to integer, the compiler gives warning. The
compiler wants prhs as the same level pointers. This kind of warning
is dangerous or not?

Probably dangerous, but since you haven't shown us the warning
or the code that produced it, it's hard to be sure.
Another method I think is to use a structer to transfer data to the
function.

Do you have some good methods on my question? Thanks.

..................
int **plhs, **prhs;

prhs = ptr_arr;
mexFunction(nlhs, plhs, nrhs, prhs);

Sorry, but I can't extract much information from this. There
are two pointer variables, each able to point at a pointer-to-int.
There's an assignment of ... well, of something unknown, and there's
a call to a function of unknown type passing unknown arguments. You
have not provided a lot of clues here ...

To the question in your Subject: In C, if you call a function
through a pointer whose type does not match the function's type, the
effect is undefined. It is likely to work on some systems, and to
fail mysteriously on others. If it works, it's by coincidence and
not by design.
 
B

Barry Schwarz

Hi,
I have a program which is originally from Matlab mex function. I would
like to rewrite it in order to run in plain C. The mex interface is a
Matlab standard. prhs is the call parameter pointer array. Some
pointers point to array while some point to integer. Matlab uses
different mxGetPr() to get pointer, or uses mxGetScalar() to get
value.

If I write the interface in general C, I try to define prhs as
pointer's point to integer. If I store some elements of plhs to
pointers while others to integer, the compiler gives warning. The
compiler wants prhs as the same level pointers. This kind of warning
is dangerous or not?

Another method I think is to use a structer to transfer data to the
function.

Do you have some good methods on my question? Thanks.

..................
int **plhs, **prhs;

prhs = ptr_arr;
mexFunction(nlhs, plhs, nrhs, prhs);

Why not use an array of pointers to void. Then you could have your
function extract each pointer and convert it to the type it needs to
be.
 
G

gwowen

If I write the interface in general C, I try to define prhs as
pointer's point to integer. If I store some elements of plhs to
pointers while others to integer, the compiler gives warning. The
compiler wants prhs as the same level pointers. This kind of warning
is dangerous or not?

The key to MEX is that the types pointed to by plhs and prhs are
(after suitable indirection) mxArray. This is an opaque type that is
used to store the data (input/output) but also encodes the *type* of
data. The mxGetPtr() and mxGetScalar() functions decode the type-
information and does the right thing. If you need to keep the
genericity, you'll need to mimic this type-encoding structure in some
way.
 
P

Paul N

Why not use an array of pointers to void.  Then you could have your
function extract each pointer and convert it to the type it needs to
be.

I don't think this will necessarily work. As I understand it, there is
no guarantee that a function pointer will still work if it is
converted to a void pointer and back.

However, I think it is allowable to convert any function pointer to
any other type of function pointer, and this will work correctly as
long as the compiler knows the correct type of the pointer at the
point it is used. I'd suggest that the OP creates a typedef for some
sort of function pointer, and stores his pointers in pointers of that
type until they are used. The compiler probably won't know what is
going on and so may issue warnings, but the reader of the code will
hopefully be able to see what is going on and can see that the
warnings can safely be ignored.
 
K

Keith Thompson

Paul N said:
I don't think this will necessarily work. As I understand it, there is
no guarantee that a function pointer will still work if it is
converted to a void pointer and back.

Correct. For example, a function pointer might be bigger than void*,
and converting to void* might lose information. (On a lot of
implementations, all pointers are the same size, and all pointer
conversions retain the original value, but the standard doesn't
guarantee that.)
However, I think it is allowable to convert any function pointer to
any other type of function pointer, and this will work correctly as
long as the compiler knows the correct type of the pointer at the
point it is used. I'd suggest that the OP creates a typedef for some
sort of function pointer, and stores his pointers in pointers of that
type until they are used. The compiler probably won't know what is
going on and so may issue warnings, but the reader of the code will
hopefully be able to see what is going on and can see that the
warnings can safely be ignored.

Yes, any function pointer can be converted to any other function pointer
type *and back again*, yielding the original value. Thus, as void* can
be used as a generic object pointer type, *any* function pointer type
can be used as a generic function pointer type. (One difference is that
there are no implicit conversions.)
 
S

Shao Miller

Yes, any function pointer can be converted to any other function pointer
type *and back again*, yielding the original value. Thus, as void* can
be used as a generic object pointer type, *any* function pointer type
can be used as a generic function pointer type. (One difference is that
there are no implicit conversions.)

(Except when converting to a compatible type.)

If you're bored, remove all lines containing 'M_ALL_IN_ONE' and split
into multiple files, or compile all as one .c file.

#define M_ALL_IN_ONE 1

/**** funcject.h */
/*** Types */
typedef struct incompatible_type * fjret_t;
typedef fjret_t fj_f();
typedef fj_f ** fjref_t;
typedef fj_f * fj_t[1];


/**** test.h */
/*** Objects */
extern fjref_t foo;


/**** test.c */
#include <stdio.h>

#if !M_ALL_IN_ONE
#include "funcject.h"
#include "test.h"
#endif /* M_ALL_IN_ONE */

/*** Types */
struct test_funcject;

/*** Function declarations */
static void show_state(struct test_funcject *);
static fj_f test1;
static fj_f test2;
static fj_f test3;

/*** Struct/union definitions */
struct test_funcject {
/* Handler */
fj_t func;
/* Other stuff */
int x;
double y;
};

/*** Objects */
static struct test_funcject my_funcject = { { test1 }, 13, 3.14 };
fjref_t foo = my_funcject.func;

/*** Function definitions */
static void show_state(struct test_funcject * this) {
printf("We have: %d and %f\n", this->x, this->y);
return;
}

/* Actual definition compatible with above declaration */
static fjret_t test1(fj_t fj) {
struct test_funcject * const this = (void *) fj;

puts("test1():");
show_state(this);
this->func[0] = test2;
puts("test1() complete.\n");
return 0;
}

/* Actual definition compatible with above declaration */
static fjret_t test2(fj_t fj, int x) {
struct test_funcject * const this = (void *) fj;

puts("test2():");
show_state(this);
this->x = x;
puts("I just set x");
show_state(this);
this->func[0] = test3;
puts("test2() complete.\n");
return 0;
}

/* Actual definition compatible with above declaration */
static fjret_t test3(fj_t fj, double y) {
struct test_funcject * const this = (void *) fj;

puts("test3():");
show_state(this);
this->y = y;
puts("I just set y");
show_state(this);
this->func[0] = test1;
puts("test3() complete.\n");
return 0;
}


/**** main.c */
#if !M_ALL_IN_ONE
#include "funcject.h"
#include "test.h"
#endif /* M_ALL_IN_ONE */

int main(void) {
/* Pretend all we know about is 'foo' */
(*foo)(foo);
(*foo)(foo, 42);
(*foo)(foo, 13.42);
(*foo)(foo);
(*foo)(foo, 99);
(*foo)(foo, 99.99);
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top