I have an old C++ code that has this line of code:
int logprintf( const char* ptr, ... );
and I am not sure what does it do exactly? should I change the code in order to be able to compile the code with new versions of the compiler?! does anybody have an idea? any help would be appreciated.
That's just C code and any compiler made since the 1980s should be able to handle it. The definition is of a varidic function, or "varargs" in C parlance.
What that does is declare a method signature, nothing more. Presumably somewhere else, either in a library you link in or in a C or C++ file you compile there's a matching implementation.
Most printf-style functions do not have a fixed number of arguments. This is what the ellipsis ... represents, zero or more arbitrary arguments go there.
Related
I saw this line of code in a source code and I simply can't understand what its meaning is even after having searched around (I don't know what exactly to search for). Can someone explain what this is for or where I can read up on it?
using f_loadLibraryA = HINSTANCE(WINAPI*)(const char* lpLibFilename);
Sorry for such a dumb question...
f_loadLibraryA becomes a type (almost like a typedef) for a function that takes a const char* as its single parameter and has a return type of HINSTANCE.
WINAPI is a #define macro that maps to a calling convention, which is not part of the C++ standard, but exists to establish how the function should be called (how parameters are loaded onto the call stack, and other low level things like that). It's usually either __stdcall or __cdecl.
It declares f_loadLibraryA to be a type alias for HINSTANCE(WINAPI*)(const char* lpLibFilename).
See also: https://en.cppreference.com/w/cpp/language/type_alias
I am trying to convert a C code to C++. In my .c file I've definitions like this:
void services(void);
void transfers(void);
Further more, a thread will initialize the above two like this:
_beginthread((void*) services,0,NULL);
_beginthread((void*) transfers,0,NULL);
When I try to compile, I got the following error at both the places above like this:
Conversion from void* to pointer to non-void required an Explicit cast: Cannot convert parameter 1 from void* to void(_cdecl*)(void*)
I am confused about this, hope you guys make it clear for me :-)
The solution is to use functions of the correct type and not cast them. Ignore the parameter if it's not relevant to the code.
void services(void*);
void transfers(void*);
_beginthread(services, 0, NULL);
_beginthread(transfers, 0, NULL);
If you absolutely can't change the functions, e.g. if you don't have access to the sources, use wrappers:
void correct_services(void*) { services(); }
_beginthread(correct_services, 0, NULL);
The compiler is helping you here - don't try to work around it by lying to it.
It looks like you are trying to convert from C++ calling standard to C calling standard. cdecl stands for C declaration.
To manually define a function to be cdecl you can use void _cdecl funct();
Try:
_beginthread((void(_cdecl*)(void*)) services, 0, NULL);
What you were doing was explicitly casting the function pointer to a non-function pointer type (void *). This was OK. But the _beginthread function expects as its first parameter a function pointer of the correct type mentioned in the error message. So you need to fix your cast.
If you're about to downvote this answer, I'd appreciate to know the reason why. I know it would be much better if user2754070 wanted to change the prototype of services (see my comments below). However, what I'm suggesting works (the answer was accepted) and, as far as I know, it is safe and standard practice in C libraries spawning threads. If you think it's not, please explain why and I'll consider deleting the answer.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
casting unused return values to void
C++ What is the purpose of casting to void?
After downloading and building the GDCM code using CMake, I stumbled upon this:
void error_callback(const char *msg, void *) {
(void)msg;
gdcmErrorMacro( "Error in gdcmopenjpeg" << msg );
}
What does the first line do? Never seen something like that. Keep in mind that I told CMake to build using Visual Studio 2010, if that matters.
It prevents unused variable warnings. Presumably the macro gdcmErrorMacro() can be #defined as an empty macro and msg would not be referenced in that case.
This prevents a compiler warning emitted when a function's formal parameters aren't used in the function.
It is a generally good idea to compile production code with warnings treated as errors, so this looks like an attempt to clear that up before msg was referred to in the macro use.
This could also have been taken care of by simply not naming a formal parameter in the first place -- in fact, that's what I'd do IRL if there is no mention of msg when using the macro:
void error_callback(const char *, void *) {
}
The parameter msg is not used by that function and the compiler will complain (warning) about unused parameters.
The (void)msg; line simply "uses" that parameter (with no effect). This way, the compiler does not generate the warning.
edit: actually, the function uses that parameter, but the macro gdcmErrorMacro could be set (through a compile-defined macro) to expand to... nothing (for example, to an empty do{}while(0); construction, as customary in the Linux kernel.
This way, the compiler will see nothing in the body of the function that makes use of the parameter msg (remember that the compiler sees the preprocessed source file, so the macros are already expanded).
In that case, after preprocessing, the compiler will see:
void error_callback(const char *msg, void *) {
(void)msg;
do{ }while(0);
}
and the sole "use" of the parameter msg would be that line (void)msg;.
I have a function as
AddSprintf(char* , ... )
I want to make compile time error if somebody is calling it without two arguments.
Currently if somebody is calling like
AddSprintf("hello")
it works. But I want to disable calling like this.
Is there any way using g++ I can force passing of argument ?
Overload AddSprintf:
void AddSprintf(const char* , ... ) {}
void AddSprintf(const char*);
Then you get a weird error message when compiling AddSprintf("hello")
But keep in mind that with C++11 you should use variadic templates because they are typesafe.
What about
AddSprintf(char* , char*, ... )
?
You can't, really. The dots stand for "zero or more arguments", and there is no way of knowing if there is any arguments. Except maybe using assembler and do some checking of the stack pointer.
As 0A0D says, it's variadic - by definition, the compiler is going to be fine with it. If you want it to fail at compiler time, you may have to pull tricks - for example, if you're unit testing, have code that makes the function fail with one argument call, so that new programmers will know they can't do that.
That said, why are you trying to do this? There may be a better solution to your problem.
If you want to stick to the same name, then you can use variadic macro:
#define AddSprintf(X,...) AddSprintf(X,__VA_ARGS__)
But be very careful with this solution, as AddSprintf would work first as text replacement in preprocessing stage. Then only it would be a function.
I have got a C function in a static library, let's call it A, with the following interface :
int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);
This function will change the value of y an z (this is for sure). I use it from within a dynamic C++ library, using extern "C".
Now, here is what stune me :
y is properly set, z is not changed. What I exactly mean is that if both are initialized with a (pointed) value of 666, the value pointed by y will have changed after the call but not the value pointed by z (still 666).
when called from a C binary, this function works seamlessly (value
pointed by z is modified).
if I create a dummy C library with a function having the same prototype, and I use it from within my dynamic C++ library, it works very well. If I re-use the same variables to call A(..), I get the same result as before, z is not changed.
I think that the above points show that it is not a stupid mistake with the declaration of my variables.
I am clearly stuck, and I can't change the C library. Do you have any clue on what can be the problem ?
I was thinking about a problem on the C/C++ interface, per instance the way a char* is interpreted.
Edit : I finally found out what was the problem. See below my answer.
It looks like a difference between the the way your C library and C++ compiler is dealing with long longs. My guess is that it is that the C library is probably pre C89 standard and actually treating the 64bit long long as a 32bit long. Your C++ library is handling it correctly and placing 64bits on the call stack and hence corrupting y and z. Maybe try calling the function through *int A(unsigned int a, unsigned long b, unsigned int *y, unsigned char z), and see what you get.
Just a thought.
This is one of those questions where there's nothing obviously wrong from what you've described, yet things aren't working the way you expect.
I think you should edit your post to give a lot more information in order to get some sensible answers. In particular, let's start with:-
What platform is this code for:
Windows, linux, something embedded
or ...?
What compiler is the C
static library built with?
What
compiler is the C++ dynamic library
built with?
What compiler is the C
which can successfully call the
library built with?
Do you have a
source-level debugger? If so, can
you step into the C code from the
C++.
Unless you're wrong about A always modifying the data pointed to by Z, the only likely cause of your problem is an incompatibility between the parameter passing conventions . The "long long" issue may be a hint that things are not as they seem.
As a last resort, you could compare the disassembled C++ calling code (which you say fails) and the C calling code (which you say succeeds), or step through the CPU instructions with the debugger (yes, really - you'll learn a good skill as well as solving the problem)
As far as I know, long long is not part of standard C++, maybe that is the source of your problem.
dunno. Try to debug-step into A and see what happens (assembly code alert!)
Maybe you can wrap the original function in a C library that you call from your C++ library?
Based on your points 2 and 3, it seems like this could work.
If it doesn't, it gives you another debug point to find more clues - see which of your libraries the failure first pops up in, and check why 2 and 3 work, but this doesn't - what is the minimal difference?
You could also try to examine the stack that is set up by your function call in each case to check if the difference is here -- considering different calling conventions.
Step 1: Compare the pointers y and z passed from the C++ side with those received by the C function.
P.S. I don't want to sound obvious, but just double-checking here. I suppose when you say that z is modified just fine when called from a C binary, you mean that the data where z is pointing is modified just fine. The pointers y and z themselves are passed by value, so you can't change the pointers.
Another wild guess: are you sure you're linking against the right instance of the function in your C library? Could it be that there are several such functions available in your libraries? In C the linker doesn't care about the return type or the parameter list when deciding how to resolve a function -- only the name is important. So, if you have multiple functions with the same name...
You could programmatically verify the identity of the function. Create a C library that calls your function A with some test parameters and that works fine and that prints the pointer to function A. Link the library into your C++ app. Then print the pointer to the original A function as seen from the C++ code and compare the pointer with that seen by your C library when invoked in the same process.
Again, an obvious one, but who knows... Are you sure the C function you're invoking is stateless, meaning its output depends only on its inputs? If the function isn't stateless, then it might be that the "hidden" state is responsible for the different behavior (not changing the data pointed to by z) of the function when invoked from your C++ app.
First of all, I am very grateful to everyone for your help.
Thanks to the numerous ideas and clues you gave me, I have been able to finally sort out this problem. Your advices helped me to question what I took for granted.
Short answer to my problem : The problem was that my C++ library used an old version of the C library. This old version missed the 4th argument. As a consequence, the 4th argument was obviously never changed.
I am a bit ashamed now that I realised this was the problem. However, I was misslead by the fact that my code was compiling fine. This was due to the fact that the C++ library compiled against the correct version of the C lib, but at runtime it used the old version statically linked with another library that I was using.
C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
|
------> C lib (P) v.1.1
(N) is a dynamic library which is statically linked with (P) version 1.0.
The compiler accepted the call from (M) to the function with 4 arguments because I linked against (P) version 1.1, but at runtime it used the old version of (P).
Feel free to edit this answer or the question or to ask me to do so.
In your C++ program, is the prototype declared with extern "C"?