Is this safe now?
#include <stdio.h>
#include <string.h>
long lee( void *v1)
{
long i1;
memcpy(&i1,v1,sizeof(long));
return i1;
}
//Added conversion to double:
double lee_d( void *v1)
{
double i1;
memcpy(&i1,v1,sizeof(double));
return i1;
}
void main()
{
long val=1777777;
long ii;
ii=lee((void *) &val);
double dd=377e-177;
dd=lee_d((void *) &dd);
ii=ii;
}
It works well under MS studio.
I do not use this pointer translations but when using curl libraries
The integral division will happen before the adding of 0.99999 therefore you are going to get an integer, which may be 0, 1, 2, add an arbitrary 0.99999 to it which achieves nothing, then cast it back to long.
size1 could still be 0 so val[0] might not be valid.
It is also difficult to know what you are trying to achieve.
To answer your question directly, it is not safe.
As far as lee() and your call to it goes, yes it's safe.
As has been said the (void *) are unneccessary & should be avoided until you know what you're doing. In the function declaration concerned it just means the function takes a pointer to something but it doesn't matter what the type of 'something' is.
E.g.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
static void doit(int *); // Function Prototypes. VERY IMPORTANT.
static void doitAgain(void *);
int main(int argc, char *argv[]) {
int i = 0x12345;
doit(&i);
doitAgain(&i);
}
static void doit(int *b)
{
int *foo = malloc(sizeof(int));
memcpy(foo, b, sizeof(int));
fprintf(stdout, "foo is 0x%x\n", *foo);
}
static void doitAgain(void *b)
{
int *foo = malloc(sizeof(int));
memcpy(foo, b, sizeof(int));
fprintf(stdout, "foo is 0x%x\n", *foo);
}
And when we run it:
$ make
cc main.c -o main
$ ./main
foo is 0x12345
foo is 0x12345
Related
While messing around with the type syntax, I noticed this is legal :
typedef int *((* T)[10]);
T fun(){
return 0;
};
int main(int argc, char * argv[]){
//int c = fun(); // (1)
return 0;
}
...And if you uncomment (1), then you get an error message of this kind (GCC / Clang) : "error: cannot initialize a variable of type 'int' with an rvalue of type 'T' (aka 'int *((*)[10])')" (Normal so far). Notice however the "aka" that points out the type is an alias of int *((*)[10]) and not simply int ***
However, It seems impossible to declare a function with this type without using a typedef :
int *((*)[10]) fun(){ // The compiler does not approve
return 0;
};
int *((* fun2)[10]) (){ // The compiler does not approve either
return 0;
};
int main(int argc, char * argv[]){
//int c = fun(); // (1)
return 0;
}
...Then I was wondering why ?
(the question is for the C language, but it looks like it's the same for C++)
This type:
typedef int *((* T)[10]);
Is a pointer to an array of size 10 whose members are of type int *. This is not the same as an int ***.
As for creating a function that returns this type, you would need this:
int *(*fun())[10] {
return 0;
};
But using a typedef makes this much clearer.
int *((*fun())[10]) {
return 0;
};
... Yup. You should probably stick to the typedef for the sake of readability :)
The original
typedef int *((* T)[10])
can shed the outer parens:
typedef int *(* T)[10]
Or aligned with dbush's function:
typedef int *(* T )[10]
int *(* fun() )[10]
This is an elaboration to an earlier question: How to reset state machines when unit testing C
There is also a similar question but i don't the answer match my problem and i have some examples i wish to present: Exporting a function pointer from dll
I have two sets of code that i expect should do the same but the latter crashes.
Using mingw32 and Win7.
The function to be exported. This is to be considered legacy and unmutable.
addxy.c
int addXY(int x, int y)
{
return x + y;
}
addxy.h
int addXY(int x, int y);
The working example
main.c
#include <stdio.h>
#include "addxy.h"
typedef int (__cdecl *addXYWrap_t)(int a, int b);
addXYWrap_t addXYWrap = (addXYWrap_t)addXY;
void main()
{
printf("result: %d", addXYWrap(3, 4));
}
Yielding
result: 7
The crashing example
addxydll.c
#include <stdio.h>
#include "addxy.h"
typedef int (__cdecl *addXYWrap_t)(int a, int b);
__declspec(dllexport) addXYWrap_t addXYWrap = (addXYWrap_t)addXY;
main.c
#include <windows.h>
#include <stdio.h>
typedef int (__cdecl *func)(int a, int b);
void main()
{
HINSTANCE loadedDLL = LoadLibrary("addxy.dll");
if(!loadedDLL) {
printf("DLL not loaded");
return;
} else {
printf("DLL loaded\n");
}
func addition = (func)GetProcAddress(loadedDLL, "addXYWrap");
if(!addition) {
printf("Func not loaded");
return;
} else {
printf("Func loaded\n");
}
printf("result: %d", addition(3, 4));
}
Yielding
DLL loaded
Func loaded
before it chrashes.
The crash gives no information as to why or what.
Is it a syntactical error or conceptional one?
func addition = (func)GetProcAddress(loadedDLL, "addXYWrap");
This call to GetProcAddress returns the address of addXYWrap, not its value. Since addXYWrap is a function pointer (of the same type as func), that means it returns a pointer to a function pointer, or a func*.
Try changing that line to this:
func addition = *(func*)GetProcAddress(loadedDLL, "addXYWrap");
Or, alternatively:
func* addition = (func*)GetProcAddress(loadedDLL, "addXYWrap");
and then (*addition)(3, 4)
So, based on comments above, you appear to be overthinking it. If you did need a function pointer, then to correctly call it, you must first dereference GetProcAddress like so:
func addition = *(func*)GetProcAddress(loadedDLL, "addXYWrap");
However, a much more convenient solution is to just wrap the function:
__declspec(dllexport) int myAddXY(int x, int y)
{
return addXY(x, y);
}
int addXY(int x, int y)
{
return x + y;
}
__declspec(dllexport) addXYWrap_t addXYWrap = (addXYWrap_t)addXY;
This is an error. You have to export function, not a global pointer. That is,
/* addxy.c */
__declspec(dllexport) int addXY(int x, int y)
{
return x + y;
}
....
/* main.c */
func addition = (func)GetProcAddress(loadedDLL, "_addXY");
Argument of type void (*)(int) is incompatible with parameter of type __sighnd64_t
Below is my simple code:
#include <iostream>
#include <string>
#include <signal.h>
#include <ctype>
#include <stdlib.h>
#include <stdio.h>
typedef struct mystrcut
{
int a;
char *b;
} mystr;
void set_string ( char **, const char * );
void my_handler(int s)
{
printf("Caught signal %d\n",s);
exit(1);
}
int main()
{
const std::string str1[] = {"hello1", "hello2"};
char str2[50];
size_t size1 = str1[1].size();
cout << size1;
memcpy (str2, str1[1].c_str(), size1);
cout << str2;
mystr *m = NULL;
m = new mystrcut;
m->a = 5;
set_string(&m->b, "hello");
cout << m->b;
delete []m->b;
// void (*prev_fn)(int);
signal (SIGINT,my_handler);
return 0;
}
void set_string ( char **a, const char *b)
{
*a = new char [strlen(b)+1];
strcpy (*a, b);
}
I am working on openvms. Can I avoid the compilation error by some kind of type casting? My compiler expects `__sighnd64_t __64_signal(int, __sighnd64_t);
Adding around the handler extern c has worked. Thanks
Signal handling is not a C++, but a C. This error is bit strange...
In such cases, try to use extern "C" around your handler (to define it as C function), as https://stackoverflow.com/users/775806/n-m said in comments. Modern <signal.h> from openvms already has extern "C" inside: http://wasd.vsm.com.au/conan/sys$common/syslib/decc$rtldef.tlb?key=SIGNAL&title=Library%20/sys$common/syslib/decc$rtldef.tlb&referer=http%3A/wasd.vsm.com.au/conan/sys$common/syshlp/helplib.hlb.
HP docs says only about C, not a C++.
Another doc says that signal handler (catcher) must be declared in C as
void func(int signo);
I have a C library function that expects a function pointer for callback, and I want to pass in a C++ member function. The C++ function modifies a member variable, so I can't use a static free function (as suggested in several similar posts). My attempt (shown below) fails with a compiler error.
This post comes closest to what I need:
Using a C++ class member function as a C callback function
How can I do this without static functions? Thanks!
test.h
#ifndef TEST_H_
#define TEST_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*handler_t)(int foo, void *bar);
void set_handler(handler_t h);
#ifdef __cplusplus
}
#endif
#endif
test.c
#include "test.h"
#include <stdlib.h>
static handler_t handler_ = NULL;
void set_handler(handler_t h) {
handler_ = h;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar);
}
test.cpp
#include "test.h"
#include <iostream>
using namespace std;
class Foo {
public:
Foo() : ctr_(0) {};
// handler needs to access non-static variable, so it can't be static
void handler(int foo, void *bar) { ++ctr_; }
private:
int ctr_;
};
int main(int argc, char **argv) {
// error: can't convert to "void (*)(int, void*)"
set_handler(&Foo::handler);
cout << "done" << endl;
return 0;
}
GCC barf
$ gcc test.cpp test.c
test.cpp: In function ‘int main(int, char**)’:
test.cpp:18: error: cannot convert ‘void (Foo::*)(int, void*)’ to ‘void (*)(int, void*)’ for argument ‘1’ to ‘void set_handler(void (*)(int, void*))’
It is not possible, at least with that handler_t signature.
While you can create a free function on your .cpp to wrap the member call, you need a pointer to the Foo instance:
void my_wrap(int foo, void* bar) {
Foo* some_foo_instance = ...;
some_foo_instance->handler(foo, bar);
}
int main(int argc, char **argv) {
set_handler(&my_wrap);
}
You need some void* to pass the Foo instance as a handler attribute:
// Header
typedef void (*handler_t)(int foo, void *bar, void* arg1);
void set_handler(handler_t h, void* arg1);
// Impl.
void set_handler(handler_t h, void* arg1) {
handler_ = h;
handler_arg1_ = arg1;
}
// cpp
void my_wrap(int foo, void* bar, void* arg1) {
Foo* some_foo_instance = static_cast<Foo*>(arg1);
some_foo_instance->handler(foo, bar);
}
// main
int main(int argc, char **argv) {
Foo some_concrete_instance;
set_handler(&my_wrap, static_cast<void*>(&some_concrete_instance));
}
The big question is how many times you need to call set_handler multiple times to call methods on different objects. If this answer is one, you can do something like this:
#include <boost/function.hpp>
class HandlerContext
{
static boost::function<void (int, void*)> s_func
static void forward(int foo, void* bar)
{
s_func(foo, bar);
}
public:
static void set(boost::function<int, void*> const& f)
{
s_func = f;
set_handler(&HandlerContext::forward);
}
};
If the answer is "more than once", you can have multiple forwarding functions that get their function objects out of an array. You will need to preassign slots in this case, because the function in use will indicate which callback to make.
This sentence:
I have a C library function
This means you can NOT pass it any C++ object.
If the library you are using is a C library it does not know about C++ so it can not using anything that is C++ it can only use C stuff.
You MUST make it call a free function in you code.
Now your free function can then call a method on an object (that is why C callbacks have a void* parameter (so you can pass context to the callback)).
Suppose you create a mapping function:
Foo *inst = // some instance of Foo you're keeping around...
void wrapper(int foo, void *bar){
inst->handler(foo, bar);
}
Then use wrapper as the callback. Instance semantics in a callback are kind of strange, so I'm not sure how you're going to be sure you bind to the correct instance -- if this is a singleton maybe that doesn't matter.
Here is an ugly hack I invented awhile ago to solve this problem:
#include <boost/function.hpp>
#include <boost/bind.hpp>
using ::boost::function;
using ::boost::bind;
typedef int (*callback_t)(const char *, int);
typedef function<int(const char *, int)> MyFTWFunction;
template <MyFTWFunction *callback>
class callback_binder {
public:
static int callbackThunk(const char *s, int i) {
return (*callback)(s, i);
}
};
extern void register_callback(callback_t f);
int random_func(const char *s, int i)
{
if (s && *s) {
return i;
} else {
return -1;
}
}
MyFTWFunction myfunc;
class FooClass {
public:
virtual int callme(const char *s, int x) { return 0; };
};
int main(int argc, const char *argv[])
{
FooClass foo;
myfunc = bind(&FooClass::callme, &foo, _1, _2);
register_callback(&callback_binder<&myfunc>::callbackThunk);
return 0;
}
This could probably be fixed to use stuff from TR1 and remove the dependency on Boost.
And also, of course, myfunc is a global variable. It has to be a global variable. You must have one global variable per different possible object you'd want to call back into. OTOH, you can have as many of these globals as you want.
The main issue here is that it is absolutely impossible to do what you want within the given constraints. The pointer to the object you want to call back into has to come from somewhere. In some languages (like Python for example) you can create a function on-the-fly that has it's own copy of the object pointer. This cannot be done in C++. All functions must exist completely at compile time. You cannot create new function instances at run time.
With C++0x, you can sort of create functions at runtime with lambda functions. But these functions have an unspecified type and there is absolutely no way you could ever then pass them to a C function and have it work. Lambda expressions are meant to be supplied as template parameters and it's pretty hard to use them for anything else because their address can't be taken, and even if it could you ccouldn't actually know what type the pointer is pointing to.
I highly recommend not using it. The little void * most callback interfaces allow you to specify that gets handed back to you along with the data is meant to hold an object pointer of some kind. If possible, you should be doing that instead.
If you have control over how handler is defined, I recommend using Boost function objects instead of function pointers.
If you HAVE to use function pointers, define handler_t with an extra void* whose value is passed along with the handler, watch out for the gotchas Martin York linked in a comment. Then you have something like this:
typedef void (*handler_t)(int foo, void *bar, void *data);
static handler_t handler_ = NULL;
static void* handler_data_ = NULL;
void set_handler(handler_t h, void *d = NULL) {
handler_ = h;
handler_data = d;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar, handler_data_);
}
void foo_handler(int foo, void *bar, void *data) {
Foo *fooObj = static_cast<Foo*>(data);
fooObj->handler(foo, bar);
}
// in main
set_handler(foo_handler, &some_foo_object);
I would like to create a function that takes a variable number of void pointers,
val=va_arg(vl,void*);
but above doesn't work, is there portable way to achieve this using some other type instead of void*?
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void
myfunc(void *ptr, ...)
{
va_list va;
void *p;
va_start(va, ptr);
for (p = ptr; p != NULL; p = va_arg(va, void *)) {
printf("%p\n", p);
}
va_end(va);
}
int
main() {
myfunc(main,
myfunc,
printf,
NULL);
return 0;
}
I'm using Fedora 14..
Since you have a C++ tag, I'm going to say "don't do it this way". Instead, either use insertion operators like streams do OR just pass a (const) std::vector<void*>& as the only parameter to your function.
Then you don't have to worry about the issues with varargs.