void pointers

S

steve

Hey guys,
I have a delemna which I can't figure out.
This is regarding "void pointers" and I confess, I really don't
understand them nearly enough to even understand what the problem is.

I'm using a "void" type array as an instrument to hold parameters of
non-pre-determined types,
like so:
Code:
  void * params[5];

Then I setup my data parameters similar to this:

Code:
  int int_param_values[5] = {1,2,3,4,5};

  char **str_param_values;

  str_param_values = malloc(5 * sizeof(char *));
  str_param_values[0] = malloc(10 * sizeof(char));
  strcpy(str_param_values[0], "hello");

  double dbl_param_values[5] = {1.1, 2.2, 3.3};

I can then assign my data values, to the array,
like so:

Code:
  params[indx] = (void*)int_param_values[ndx];

//-or-
  params[indx] = (void*)str_param_values[ndx];

These two methods compile just fine and work as expected.
However, this statement will not compile:

Code:
  params[indx] = (void*)dbl_param_values[ndx];

and generates this compiler error:

"...cast from 'double' to 'pointer to void' is illegal"



When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:

MyFunction(params[0], params[1], etc.);

Does sombody understand void pointers enough to explain why the above
doesn't work and possibly offer a solution to the problem.

Thanks,
Steve
 
B

Ben Bacarisse

steve said:
I have a delemna which I can't figure out.
This is regarding "void pointers" and I confess, I really don't
understand them nearly enough to even understand what the problem is.

I'm using a "void" type array as an instrument to hold parameters of
non-pre-determined types,
like so:

void * params[5];

Then I setup my data parameters similar to this:

int int_param_values[5] = {1,2,3,4,5};

char **str_param_values;

str_param_values = malloc(5 * sizeof(char *));
str_param_values[0] = malloc(10 * sizeof(char));
strcpy(str_param_values[0], "hello");

double dbl_param_values[5] = {1.1, 2.2, 3.3};

I can then assign my data values, to the array,
like so:

params[indx] = (void*)int_param_values[ndx];

//-or-
params[indx] = (void*)str_param_values[ndx];

These two methods compile just fine and work as expected.
However, this statement will not compile:

params[indx] = (void*)dbl_param_values[ndx];

and generates this compiler error:

"...cast from 'double' to 'pointer to void' is illegal"

You have three examples of conversions from some type or other to void *
with varying degrees of "validity". The conversion from a char *
(str_param_values[ndx]) is entirely well-defined and safe. The
conversion from int (int_param_values[ndx]) is implementation-defined
and the conversion from a double is just plain not on.

void * can only be used as a generic type for pointers. You could, for
example, do this:

params[indx] = &int_param_values[ndx];
params[indx] = str_param_values[ndx];
params[indx] = &dbl_param_values[ndx];

(not one after the other, of course) since all the "parameters" are in
objects and can be pointed to. Note two things: (a) the string is
already a pointer to you don't need the & and (b) there are no casts.
Contrary to common opinion, you rarely need casts in C. While you are
learning, treat the apparent need for one and big red flag.
When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:

MyFunction(params[0], params[1], etc.);

Does sombody understand void pointers enough to explain why the above
doesn't work and possibly offer a solution to the problem.

This will work if everything is a pointer and all you do is convert
different pointer types to void *.
 
E

Edward

steve said:
Hey guys,
I have a delemna which I can't figure out.
This is regarding "void pointers" and I confess, I really don't
understand them nearly enough to even understand what the problem is.
A void pointer is an address of a region of memory (which may or may not
be occupied). It is an error to attempt to use a void value in an
expression, hence why compilers will often warn you if you dereference a
void pointer.
(Note to the regulars: I'm probably not being perfectly accurate here,
but I don't think c.l.c pedantry is what steve needs)
(Note to steve: the correct spelling is dilemma)
void * params[5];
This creates an array of 5 pointers to void. It does not create an
array of "void" (as you seem to think).
int int_param_values[5] = {1,2,3,4,5};

char **str_param_values;

str_param_values = malloc(5 * sizeof(char *));
str_param_values[0] = malloc(10 * sizeof(char));
strcpy(str_param_values[0], "hello");

double dbl_param_values[5] = {1.1, 2.2, 3.3};
This creates an array of int, an array of char *, and an array of
double, and initialises them in various ways.
Note two things: firstly, it would probably make more sense for
str_param_values to be an array of 5 char *, and allocated on the stack,
with
char *str_param_values[5];
There is no obvious need for it to be on the heap.
Secondly, you have not tested the return value of malloc() in either of
these calls; I realise this is only example code (incidentally, you will
get more informative answers if you post actual code; then we know what
you're trying to achieve!) but nonetheless it bears pointing out.
I can then assign my data values, to the array,
like so:
params[indx] = (void*)int_param_values[ndx];
This is casting an int to a void *. This is generally incorrect as an
int is not a pointer type. It just so happens that you are, IIRC,
allowed to do this by a special provision to allow the use of integer
expressions as pointers. In this case this is clearly not what you are
doing as, for instance, params[0] is now (void *)1; this is now a
pointer to the memory with address 1, which probably isn't even mapped
in your program's address space (if you're on a memory managed
architecture. On, say, an embedded system you might want to do this).
params[indx] = (void*)str_param_values[ndx];
This is casting a char * to a void *. This is allowed because both are
pointer types. params[indx] now points to the first character of
str_param_values[ndx].
These two methods compile just fine and work as expected.
However, this statement will not compile:
params[indx] = (void*)dbl_param_values[ndx];
This is casting a double to a void *. This is not allowed; a double is
not the same size as, nor anything like, a void *. Unlike an int it
cannot even reasonably be interpreted as an address; what location in
memory would (void *)0.5 point to? It's just silly really!
and generates this compiler error:

"...cast from 'double' to 'pointer to void' is illegal"
Quite right too.
When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:

MyFunction(params[0], params[1], etc.);
There are two appropriate methods I can think of. One is to use
varargs; if the function's first argument gives it some way of deducing
the types of the remaining arguments, it can do so. This is for
instance how the *printf() family of functions work.

The other is to use void *, but populate it not with the data themselves
but with pointers to them; for instance your doubles would become
something like:
params[indx] = (void *)&dbl_param_values[ndx];
where we assign the /address/ of the double to the pointer; we are now
casting a double * to a void *, which makes much more sense as both are
pointer types.

One question I do have: given your function prototype as you have it,
where the only arguments are the params[] elements, how does the
function know to what the pointers refer (i.e., whether you have used an
int, a double, a char *, or whatever).
If, of course, it is simply, say, printing their addresses, it need not
know; but if it is using their values, it will have to be told, since
not only does it not know their true types, it doesn't even know their
sizes, and a pointer without size information is not much use.

Note also that you cannot make an array of void and store the values
(ints, doubles etc.) in that, because void has no storage size.

Perhaps the real solution to your problems, however, is to use a struct
or union.

I can't really give any more specific advice without some information as
to what you're trying to achieve.

-Edward
 
E

Edward

Edward said:
steve said:
params[indx] = (void*)int_param_values[ndx];
This is casting an int to a void *. This is generally incorrect as an
int is not a pointer type. It just so happens that you are, IIRC,
allowed to do this by a special provision to allow the use of integer
expressions as pointers.
I of course mean that your implementation is likely to allow it. It is
in fact implementation defined as Ben Bacarisse points out.
-Edward
 
B

Ben Bacarisse

Edward said:
steve wrote:
However, this statement will not compile:
params[indx] = (void*)dbl_param_values[ndx];
This is casting a double to a void *. This is not allowed; a double
is not the same size as, nor anything like, a void *.

void * and double are the same size on at least one system I have! The
potential difference in size is not the reason for the conversion being
undefined (if were, the same blanket undefinedness would have to apply
to at least some integer types and it doesn't).
Unlike an int
it cannot even reasonably be interpreted as an address; what location
in memory would (void *)0.5 point to? It's just silly really!

Yes, that's the real reason it's undefined. There is no obvious meaning
for the construct and little to be gained by permitting it.

If you happen to have a void * large enough to hold a double, and you
really want to skate on C's thin ice, you can always copy the
representation of the double rather than trying to do a conversion.

<snip>
 
S

steve

Hey guys,
I have a dilemma which I can't figure out.
This is regarding "void pointers" and I confess, I really don't
understand them nearly enough to even understand what the problem is.

I'm using a "void" type array as an instrument to hold parameters of
non-pre-determined types,
like so:
Code:
  void * params[5];

Then I setup my data parameters similar to this:

Code:
  int int_param_values[5] = {1,2,3,4,5};

  char **str_param_values;

  str_param_values = malloc(5 * sizeof(char *));
  str_param_values[0] = malloc(10 * sizeof(char));
  strcpy(str_param_values[0], "hello");

  double dbl_param_values[5] = {1.1, 2.2, 3.3};

I can then assign my data values, to the array,
like so:

Code:
  params[indx] = (void*)int_param_values[ndx];

//-or-
  params[indx] = (void*)str_param_values[ndx];

These two methods compile just fine and work as expected.
However, this statement will not compile:

Code:
  params[indx] = (void*)dbl_param_values[ndx];

and generates this compiler error:

"...cast from 'double' to 'pointer to void' is illegal"

When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:

  MyFunction(params[0], params[1], etc.);

Does sombody understand void pointers enough to explain why the above
doesn't work and possibly offer a solution to the problem.

Thanks,
Steve

Hello Ben,
thanks for the reply.

<snip>
params[indx] = &dbl_param_values[ndx];
<snip>

I actually tried this, before-hand, and it didn't seem work.
It seemed to me that it should have.

Steve
 
S

steve

steve said:
Hey guys,
I have a dilemma which I can't figure out.
This is regarding "void pointers" and I confess, I really don't
understand them nearly enough to even understand what the problem is.

A void pointer is an address of a region of memory (which may or may not
be occupied).  It is an error to attempt to use a void value in an
expression, hence why compilers will often warn you if you dereference a
void pointer.
(Note to the regulars: I'm probably not being perfectly accurate here,
but I don't think c.l.c pedantry is what steve needs)
(Note to steve: the correct spelling is dilemma)
  void * params[5];

This creates an array of 5 pointers to void.  It does not create an
array of "void" (as you seem to think).>   int int_param_values[5] = {1,2,3,4,5};
  char **str_param_values;
  str_param_values = malloc(5 * sizeof(char *));
  str_param_values[0] = malloc(10 * sizeof(char));
  strcpy(str_param_values[0], "hello");
  double dbl_param_values[5] = {1.1, 2.2, 3.3};

This creates an array of int, an array of char *, and an array of
double, and initialises them in various ways.
Note two things: firstly, it would probably make more sense for
str_param_values to be an array of 5 char *, and allocated on the stack,
with
        char *str_param_values[5];
There is no obvious need for it to be on the heap.
Secondly, you have not tested the return value of malloc() in either of
these calls; I realise this is only example code (incidentally, you will
get more informative answers if you post actual code; then we know what
you're trying to achieve!) but nonetheless it bears pointing out.
I can then assign my data values, to the array,
like so:
  params[indx] = (void*)int_param_values[ndx];

This is casting an int to a void *.  This is generally incorrect as an
int is not a pointer type.  It just so happens that you are, IIRC,
allowed to do this by a special provision to allow the use of integer
expressions as pointers.  In this case this is clearly not what you are
doing as, for instance, params[0] is now (void *)1; this is now a
pointer to the memory with address 1, which probably isn't even mapped
in your program's address space (if you're on a memory managed
architecture.  On, say, an embedded system you might want to do this).
  params[indx] = (void*)str_param_values[ndx];

This is casting a char * to a void *.  This is allowed because both are
pointer types.  params[indx] now points to the first character of
str_param_values[ndx].
These two methods compile just fine and work as expected.
However, this statement will not compile:
  params[indx] = (void*)dbl_param_values[ndx];

This is casting a double to a void *.  This is not allowed; a double is
not the same size as, nor anything like, a void *.  Unlike an int it
cannot even reasonably be interpreted as an address; what location in
memory would (void *)0.5 point to?  It's just silly really!
and generates this compiler error:
"...cast from 'double' to 'pointer to void' is illegal"

Quite right too.
When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:
  MyFunction(params[0], params[1], etc.);

There are two appropriate methods I can think of.  One is to use
varargs; if the function's first argument gives it some way of deducing
the types of the remaining arguments, it can do so.  This is for
instance how the *printf() family of functions work.

The other is to use void *, but populate it not with the data themselves
but with pointers to them; for instance your doubles would become
something like:
        params[indx] = (void *)&dbl_param_values[ndx];
where we assign the /address/ of the double to the pointer; we are now
casting a double * to a void *, which makes much more sense as both are
pointer types.

One question I do have: given your function prototype as you have it,
where the only arguments are the params[] elements, how does the
function know to what the pointers refer (i.e., whether you have used an
int, a double, a char *, or whatever).
If, of course, it is simply, say, printing their addresses, it need not
know; but if it is using their values, it will have to be told, since
not only does it not know their true types, it doesn't even know their
sizes, and a pointer without size information is not much use.

Note also that you cannot make an array of void and store the values
(ints, doubles etc.) in that, because void has no storage size.

Perhaps the real solution to your problems, however, is to use a struct
or union.

I can't really give any more specific advice without some information as
to what you're trying to achieve.

-Edward

Hey Ed,
thanks for your indepth reply.
Very helpful.
(Note to steve: the correct spelling is dilemma)
Sorry for that.
I'm one of those people prone to typos and misspelling.
I should have run spell check, I usually do.

void * params[5];

This creates an array of 5 pointers to void. It does not create an
array of "void" (as you seem to think).> int int_param_values[5] = {1,2,3,4,5};
</snip>

No, I get that.
My understanding was that it was creating an "array of 5 pointers to
void".
Which I then intended to populate with the addresses of the variables.

Note two things: firstly, it would probably make more sense for
str_param_values to be an array of 5 char *, and allocated on the stack,
with
char *str_param_values[5];
</snip>

Actually, I did try that.
It did not produce the result I was hoping for.

This is casting a double to a void *. This is not allowed; a double is
not the same size as, nor anything like, a void *. Unlike an int it
cannot even reasonably be interpreted as an address; what location in
memory would (void *)0.5 point to? It's just silly really!

Clearly I'm wrong here, but, I was making the 'assumption' that a
"pointer to void" was just that,
a pointer to the address of a variable of an undertermined type.
Regardless of the size of the variable.
On a given system, are not addresses the same size ?

What I'm after here, is a "generic" mechanism for holding addresses of
mixed variable types.
i.e.: an array of addresses.
Be they of type int, or char, or double, etc.

What I'm (really) after here is to construct a 'generic mechanism' for
calling functions within DLLs at RunTime.
These DLLs, their Functions and Parameters passed are not known at
compile time.

Research indicated that void pointers was the way to do this.

Suggestions ?

Steve
 
B

Ben Bacarisse

steve said:
On Oct 5, 6:41 am, steve <[email protected]> wrote:
  void * params[5];
Hello Ben,

It's usually better to reply to the message you are commenting on --
your post seemed to be a reply to your own initial post.
thanks for the reply.

<snip>
params[indx] = &dbl_param_values[ndx];
<snip>

I actually tried this, before-hand, and it didn't seem work.
It seemed to me that it should have.

I am sure the assignment will work but you don't show how you use these
void pointers and the problem may well be there. It's not possible to
go any further if all you reveal is that "it didn't seem work"!
 
E

Edward

steve said:
Note two things: firstly, it would probably make more sense for
str_param_values to be an array of 5 char *, and allocated on the stack,
with
char *str_param_values[5];
</snip>

Actually, I did try that.
It did not produce the result I was hoping for.
Curious. It certainly should have.
Clearly I'm wrong here, but, I was making the 'assumption' that a
"pointer to void" was just that,
a pointer to the address of a variable of an undertermined type.
Regardless of the size of the variable.
On a given system, are not addresses the same size ?
Your assumption is valid; the problem is that you weren't putting a
pointer to the double into the void *, you were trying to put the double
itself into the void *. As mentioned elsewhere in the thread, the '&'
operator is what you're looking for.
What I'm after here, is a "generic" mechanism for holding addresses of
mixed variable types.
i.e.: an array of addresses.
Be they of type int, or char, or double, etc.

What I'm (really) after here is to construct a 'generic mechanism' for
calling functions within DLLs at RunTime.
These DLLs, their Functions and Parameters passed are not known at
compile time.

Research indicated that void pointers was the way to do this.
Firstly, I can't think of a good reason why you would want to do this.
It sounds as though you've come up with some idea for a 'generic
mechanism' without actually having any use cases in mind.
Besides, linking against ill-defined interfaces is a bad idea. If
you're trying to define functionality at runtime, an embedded scripting
language is the way to go.
But if you /really/ want this, void pointers will do it - but you have
to remember that what you assign to the void pointer has to, itself, be
a pointer too (hence why your double to void * cast wasn't valid). Also
remember that if you pass a pointer, the callee can modify the
referenced object. This may not be what you want.
What it /really/ sounds like is that you want function overloading
and/or dynamic types - in other words, you're trying to make C more like
C++ or Java. From my perspective that seems like a silly thing to do:
why would you want C++ in the first place - and if you do, you know
where to find it ;)
 
B

Ben Bacarisse

steve said:
steve wrote:
However, this statement will not compile:
  params[indx] = (void*)dbl_param_values[ndx];

This is casting a double to a void *.  This is not allowed; a double is
not the same size as, nor anything like, a void *.  Unlike an int it
cannot even reasonably be interpreted as an address; what location in
memory would (void *)0.5 point to?  It's just silly really!

You've quoted the whole message and added comments at the end by adding
further copies of material that you already quoted! The preferred
method is usual to interleave your remarks with the material you quote,
cutting any parts that are not needed for context.

[This text was already in your post]
Clearly I'm wrong here, but, I was making the 'assumption' that a
"pointer to void" was just that,
a pointer to the address of a variable of an undertermined type.
Regardless of the size of the variable.
On a given system, are not addresses the same size ?

First, no, not all pointers are assured to be the same size, but that's
beside the point. Edward's point is that double and void * might not be
the same size. Actually, even this matter of size is not important --
you simply can't convert a double to a void * because the language says
that this is a meaningless thing to do.

What you can do is convert a pointer to any object type to a pointer to
void. In the case of the double you need to get a pointer to it (using
&) and it is this that you can convert to void *.
What I'm after here, is a "generic" mechanism for holding addresses of
mixed variable types.
i.e.: an array of addresses.
Be they of type int, or char, or double, etc.

That's exactly what void * is for but Edward was pointing out that you
were trying to convert a double (not a pointer to one) to a void *.

<snip>
 
B

Ben Bacarisse

Edward said:
steve wrote:
Your assumption is valid;

If you mean the assumption that, on a given system, all addresses
(pointers) are the same size then this is not true. It is particularly
not true for function pointers and object pointers, but it can (at least
in theory) also not be true for other types of pointer. The C standard
says a lot about what pointers must have the same representation (which
implies the same size) if you want to know the gory details but, as you
say, it is not actually relevant to the current question.

<snip>
 
S

steve

Firstly, I can't think of a good reason why you would want to do this.
It sounds as though you've come up with some idea for a 'generic
mechanism' without actually having any use cases in mind.

No, not at all.
I have written a scripting engine and I want to be able to call DLL
functions at runtime.
Example:
crtdll.dll contains function 'exp()', which accepts one
parameter: (double),
user32.dll contains function 'MessageBoxA()' which accepts four
parameters:(hwnd, text$, caption$, uType),
crtdll.dll "" "" 'toupper()' which accepts one parameter:
(int),
etc...,

Besides, linking against ill-defined interfaces is a bad idea.  If
you're trying to define functionality at runtime, an embedded scripting
language is the way to go.

Yes.
There are numerous DLLs and an untold number of Functions within them.
That is why I want a 'generic mechanism' for passing variables to
those functions.
Calling the DLLs and Functions by name has been solved, now I need a
method of
passing parameters.

Steve
 
S

steve

Since seeing actual code can be worth a thousand words, I have written
a simple example of what I am trying to accomplish.
This sample is compilable and executable:
Code:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

void MySub_1(void);
void MySub_2(void);

void * (__stdcall *stdcall_func4)(void *, void *, void *, void *);
double (__cdecl *ccall_func1_dbl)(void*);

#define INTEGER               1
#define STRING                2
#define DOUBLE                3

   int int_params_values[5];
  char **string_params_values;
  double dbl_params_values[5];

  void * params[5];

  char dllname[32];
  char functionname[32];
   int para_meters;
   int stdcall_type = 1;
   int ccall_type = 2;
   int function_type;

int main()
{
    MySub_1();
    MySub_2();

    system("pause");
    return 0;
}
/*--------- end main ----------*/


void MySub_1()
{
    HMODULE dll_handle = 0;
    int int_params_used = 0;
    int string_params_used = 0;
    int i = 0;

/* \/ \/ \/ values determined only at runtime \/ \/ \/ */
    string_params_values = malloc(5 * sizeof(char *));

    string_params_values[0] = malloc(100 * sizeof(char));
    string_params_values[1] = malloc(100 * sizeof(char));

    strcpy(string_params_values[0], "hello world");
    strcpy(string_params_values[1], "hello");

    strcpy(dllname, "user32.dll");
    strcpy(functionname, "MessageBoxA");
    int_params_values[0] = 0;
    int_params_values[1] = 1;

    para_meters = 4;

    int params_type[5] = {INTEGER,STRING,STRING,INTEGER};
/* /\ /\ /\ values determined only at runtime /\ /\ /\ */


    dll_handle = LoadLibrary(dllname);

    if (para_meters > 0)
    {
        for (i = 0; i < para_meters; i++)
        {
            if (params_type[i] == INTEGER)
            {
                params[i] = (void*)int_params_values[int_params_used+
+];
            }
            else if(params_type[i] == STRING)
            {
                params[i] =
(void*)string_params_values[string_params_used++];
            }
        }
    }

    *(void**)&stdcall_func4 = (void*)GetProcAddress(dll_handle,
functionname);

    stdcall_func4(params[0], params[1], params[2], params[3]);        /
* call DLL */

    free(string_params_values[1]);
    free(string_params_values[0]);
    free(string_params_values);
}
/*--------- end MySub_1 ----------*/



void MySub_2()
{
    HMODULE dll_handle = 0;
    double retval;


/* \/ \/ \/ values determined only at runtime \/ \/ \/ */
    double dblVar = 1.87766;

    strcpy(dllname, "crtdll.dll");
    strcpy(functionname, "exp");

    dbl_params_values[0] = dblVar;

    int params_type[5] = {DOUBLE};
/* /\ /\ /\ values determined at runtime /\ /\ /\ */


    dll_handle = LoadLibrary(dllname);

    printf("\nparameter passed=%f\n\n", dbl_params_values[0]);


//    params[0] = (void*)dbl_params_values[0]; /* this one does not
compile */
    params[0] = &dbl_params_values[0];  /* this one produces wrong
answer */

    *(void**)&ccall_func1_dbl = (void*)GetProcAddress(dll_handle,
functionname);

    retval =  ccall_func1_dbl(params[0]);     /* call DLL */

    printf("Exponent=%f\n", retval);
    printf("\n1.0000...is wrong answer.\n");
}
/*--------- end MySub_2 ----------*/

Please excuse errors and omissions.

I hope it's obvious, (by now), that what I'm looking for here is the
ability,
in MySub_2(), to pass a double as a parameter via void pointer
"params[0]".

Steve
 
I

Ian Collins

Since seeing actual code can be worth a thousand words, I have written
a simple example of what I am trying to accomplish.
This sample is compilable and executable:
Code:
#include<windows.h>[/QUOTE]

But only for windows users!
 
I

Ian Collins

On 10/ 6/10 02:41 AM, steve wrote:

When it's all said and done, the idea is to pass the data referred to
in the array as function parameters,
like so:

MyFunction(params[0], params[1], etc.);

Does sombody understand void pointers enough to explain why the above
doesn't work and possibly offer a solution to the problem.

It looks like you are trying to build a heterogeneous container. Have
you considered an array of unions? Something like:

typedef enum { Int, Double, String } MemberType;

typedef struct
{
union
{
int intItem;
double doubleItem;
char* stringItem;
} member;
MemberType type;
} Array;

int main(int argc, char *argv[])
{
Array array[2];

array[0].member.intItem = 42;
array[0].type = Int;

array[1].member.intItem = 42.42;
array[1].type = Double;

return 0;
}
 
K

Keith Thompson

steve said:
Since seeing actual code can be worth a thousand words, I have written
a simple example of what I am trying to accomplish.
This sample is compilable and executable:
Code:
#include <windows.h>[/QUOTE]

Obviously Windows-specific.
[QUOTE]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>[/QUOTE]

Unnecessary; malloc() and friends are declared in <stdlib.h>.
(Unless you're using some non-standard declarations that your
system puts in <malloc.h>.)

[snip]
 
S

steve

But only for windows users!
Well,
that's because one of the examples calls a windows DLL.
That header file and function that uses it, can be easily commented
out from the source.
But, the code illustrates my objective.

Steve
 
S

steve

#include said:
Obviously Windows-specific.


See my prior reply, re: windows portion.
Unnecessary; malloc() and friends are declared in <stdlib.h>.
(Unless you're using some non-standard declarations that your
system puts in <malloc.h>.)


Did you have something positive to contribute to this discussion ?

Steve
 
K

Keith Thompson

steve said:
See my prior reply, re: windows portion.



Did you have something positive to contribute to this discussion ?

Yes, I did. I informed you that #include <malloc.h> is both
unnecessary (the functions are declared in <stdlib.h> and
non-portable (some systems might not provide <malloc.h>, others
might provide it with different contents).

Do you not consider that positive?
 
B

Ben Bacarisse

steve said:
No, not at all.
I have written a scripting engine and I want to be able to call DLL
functions at runtime.
Example:
crtdll.dll contains function 'exp()', which accepts one
parameter: (double),
user32.dll contains function 'MessageBoxA()' which accepts four
parameters:(hwnd, text$, caption$, uType),
crtdll.dll "" "" 'toupper()' which accepts one parameter:
(int),
etc...,

You can't get round the fact that you need to pass a single double to
exp. Having generic parameters represented as void * can help with
some of your internal organisation (e.g. it may be a way to get them
into some dispatch function) but once you have located the function to
call (exp in this case) you have to know that exp takes a double and
you'll have to turn the void * into a double to make the call.

Often, the best solution to this problem is not to try to permit calls
to arbitrary dynamic function but to provide instead a mechanism that
automates the boiler-plate code needed to interface to a given library.
It's impossible to be precise without a lot more information but this
can be done statically (a tool to make a dynamic "glue" library for your
engine from some description of the external DLL) or dynamically (some
implementation specific mechanism that can build a valid call from some
kind of prototype string or structure).
Yes.
There are numerous DLLs and an untold number of Functions within them.
That is why I want a 'generic mechanism' for passing variables to
those functions.
Calling the DLLs and Functions by name has been solved, now I need a
method of
passing parameters.

The functions will still need to be passed arguments of the type that
they expect and, what is more, these arguments have to passed using the
correct calling conventions (e.g. you can't "pretend" that exp declared
double exp(...)).

You can do this simply by writing a correct call, but that is a
compile-time solution -- hence the suggestion to automate the writing of
interface routines. I.e. you'd automate the production of lots of
functions like this:

void *engine_call_exp(void *arg1)
{
double *result = engine_allocate_object(sizeof *result);
*result = exp(*(double *)arg1);
return result;
}

A fully run-time solution will be implementation specific and will rely
on fair bit of trickery.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top