I stumbled upon a rather exotic c++ namespace problem:
condensed example:
extern "C" {
void solve(lprec * lp);
}
class A {
public:
lprec * lp;
void solve(int foo);
}
void A::solve(int foo)
{
solve(lp);
}
I want to call the c function solve in my C++ member function A::solve. The compiler is not happy with my intent:
error C2664: 'lp_solve_ilp::solve' : cannot convert parameter 1 from 'lprec *' to 'int'
Is there something I can prefix the solve function with? C::solve does not work
To call a function in the global namespace, use:
::solve(lp);
This is needed whether the function is extern "C" or not.
The C functions are in the global namespace. So try
::solve(lp)
Please try ::solve
Simply ::solve(lp). Note you also need a semicolon after your class declaration.
Related
Assume that we have a C++ project. We can use a function which defined in a C file in the C++ project through extern "C" keyword. Example:
C code: cfile.c
#include <stdio.h>
void f(void)
{
printf("\n This is a C code\n");
}
Cpp Code: cppfile.cpp
#include <iostream>
extern "C" {
void f();
}
int main(void)
{
f();
return 0;
}
So, can we do that for the opposite case:
Cpp code: cppCode.cpp
struct MyClass
{
virtual void f(const char* text);
void func(const char* text);
};
Can we implement f method and func method in a C file (for instance: cCode.c) ??? Is that possible ? (Just the question for my personal purpose)
You can't do this directly. However, there is a workaround (of sorts). You can have a function with "C" linkage which returns the pointer to the object of the class - presumably dynamically allocated - converted to void*.
Than you can implement functions which would map to functions inside the class, but would take one additional argument - void*, which would be the address obtained from the call to creation function above. They would simply convert this void* to the type of the class and call it's member.
In the end, you'd need a dispose function which would corectly delete the pointer.
I saw this question and I tried to do as the answer to that question said. To use the extern keyword in the header file to define an array and then declare it outside of that namespace or class in a other cpp file.
It didn't work for me really, I'm not sure if it because I'm using a void pointer array (i.e void* array[]) or if it's just my ignorance that prevents me from seeing the problem.
This is the shortest example I can come up with:
[cpp.cpp]
#include "h.h"
void main(){
void* a::b[] = {
a::c = a::d(1)
};
}
[h.h]
namespace a{
struct T* c;
struct T* d(int e);
extern void* b[];
}
So the problem is that I receive the error:
IntelliSense: variable "a::b" cannot be defined in the current scope
And I have no clue why that is.
First, you should declare main() as int ! See here why.
Declaring your array as extern in a namespace means that it belongs to the namespace but is defined somewhere ele, normally in a separate compilation unit.
Unfortunately, in your main(), you try to redefine the element as a local variable. This explains the error message you receive.
You shoud do as follows:
#include "h.h"
void* a::b[] { a::c, a::d(1) }; // global variable belonging to namespace
int main() // int!!!
{
/* your code here */
}
The code will compile. The fact that a::b[] is defined in the same compiling unit is accepted. But the linker will complain because a::d(1) is a call to the function d returning a pointer to a struct, and this function is defined nowhere.
Therfore you should also define this:
namespace a {
struct T* d(int e)
{
return nullptr; // in reality you should return a pointer to struct T
}
}
Interestingly, struct T does not need to work for this code to compile and link.
I have this code in a plain C static library:
extern "C" {
typedef void (__cdecl* VisitChildren)(Option*);
void __cdecl DoVisitChildren(Children* List, VisitChildren Visitor);
}
And I'm trying to use it from some C++ code (unit tests) using a lambda.
...
DoVisitChildren(children, [&] (Option* option) {
...
});
I'm getting the compiler error C2664 ... cannot convert parameter 2 from 'unittests::UnitTest1::TestBuild::<lambda_b286d160b9bab3e09ab93cd59fc49f0b>' to 'VisitChildren'
If I remove the capture '&' it compiles and works, but I need to capture some bits and bobs.
Is this possible?
A closure created by a lambda expression can be implicitly converted to a function pointer, but only if it does not capture any variables. Also, it will be converted to a pointer to an extern "C++" function, not an extern "C" function, and technically those are incompatible types.
So no, you can't do this.
A hacky workaround is to store your actual closure in a global variable and pass a callback which invokes it. This will only work if your program is single-threaded and the DoVisitChildren call does not store the callback for later use.
std::function<void(Option*)> callback;
extern "C" void __cdecl invoke_callback(Option* o) { callback(o); }
// ...
callback = [&] (Option* option) { /* ... */ };
DoVisitChildren(children, invoke_callback);
It would seem I can declare a function at block scope:
int main()
{
void f(); // OK
}
However I can't define it:
int main()
{
void f() {}; // ERROR
}
My question is, of what use is a function declaration at block scope? What is a use case?
It's sometimes a shortcut to declaring and calling an externally-linked function which itself isn't publically defined in a header. For example, imagine you were linking against a C library which you knew provided a LibDebugOn(int) call but hadn't defined it in a header. It can be a shortcut to declare and call it in one place:
void myFunc() {
// call "Lib" but turn on debugging via hidden API
extern "C" void LibDebugOn(int); // declare hidden C-linked function
LibDebugOn(1); // call it
// do something with the library here...
LibDebugOn(0); // turn off lib debugging now
}
In fairness this is usually only worthwhile for a one-off quick hack, and not something to be encouraged.
You can define it. http://ideone.com/kJHGoF
#include <cstdio>
int main()
{
void f(); // Forward declare function named "f" returning void in the
// global namespace.
f();
}
/*
void g()
{
f(); // ERROR!
}
*/
void f()
{
std::puts("hello!");
}
I'm not sure why someone would actually want to use this. It is in the language this way for backwards compatibility with C; but I've got no idea what someone would do with this in C.
I'm using Visual Studio 2012 with SDL and I'm doing a simple threading task but I always get these errors:
argument of type "int (mainGame::*)(void *ptr)" is incompatible with parameter of type "int (__cdecl *)(void *)"
The other error I'm getting:
error C3867: 'mainGame::gameEvents': function call missing argument list; use '&mainGame::gameEvents' to create a pointer to member
This is how the function is written:
int gameEvents(void *ptr){
//do things here.
return 0;
}
This is the code I'm using to call the function:
SDL_Thread* gh;
gh = SDL_CreateThread(gameEvents,NULL);
Since you're using C++, you need to declare your function with C linkage, since that's what SDL expects, being a C library itself:
extern "C" int gameEvents(void *ptr);
Change gameEvents() to static. Otherwise your member function will have a "hidden" first argument for the this pointer that C APIs like SDL don't know about.
If you need access to instance data do something like this:
static int mainGame::gameEvents(void *ptr)
{
mainGame* game = (mainGame*)ptr;
//do things here.
return 0;
}
...
mainGame game;
SDL_Thread* gh;
gh = SDL_CreateThread( mainGame::gameEvents, &game );