c++ class scope issues
This is my first time here, so I hope I meet the expectations for the forums.
I am trying to make a futures contracts trading program interfacing with interactive brokers' twsapi. I found some c code which seems to make the interface simple, but I'm getting compiler errors that I have never seen before.
I have a market class and a cell class. the market class contains a 2d array of cells in addition to other information like the current trading price etc...
Here is how my files depend on eachother right now (arrows point to included files):
the TWSAPI essentially gives me a void event_update(data, data, data) function to override, which is called whenever data is received from the server. I need to take that data and store it in my market class. The problem is that I can't access my market object from within the function. Unless it is passed as a parameter, I can't think of how to do this, and I haven't been successful with passing it in as a parameter because I'm trying to pass a class through a c function. I could sure use some help here. I feel like there should be a way to declare my market as a global or change the twsapi.c into a cpp file (I'm not sure if this is as easy as I think it should be). I signed a NDA and some of the code is not allowed to become public so if you need to see code, let me know and I'll give everything I can.
TWSAPI.h <--- TWSAPI.c
market.h <--- market.cpp
cell.h <--- cell.cpp
Thanks for your time.
So you're trying to modify a c++ object from a C function?
Making it into a cpp file would probably be first option I'd consider.
What I'd try is this:
In TWSAPI.h declare a market data struct that holds the relevant data of the market class. When the file is included all the function prototypes are in an extern "C" block.
Your market class needs to hold a market data struct. I think this can simply be a data member. Make event_update take a pointer to the market data struct.
I think that would work, but I'm not 100% sure. It wouldn't surprise me if that worked on some compilers but not on others.
Worst comes to worst, you can make the market data a big char array, and rely on accessors methods/functions to get the data. That's bound to work, because the sizes of char arrays are well defined as being the same in c and c++.
I would first try copying the twsapi.c file to a twsapi.cpp file, and then try compiling it. Depending on how it was written it may be fairly easy to convert. There are a few differences between the languages, but if you know both languages, translating it may be easy. If it's a short file, it may even compile as is. If this isn't possible then see below.
If the market class only contains data (no member functions), then you should be able to pass a pointer the market class to the function:
If the market class also contains member functions, then I'm not sure it's possible. You may have to make a struct within the market class which contains all the data for the market class, then pass that to the C function.
void event_update(marketClass *market)
I've received good suggestions so far so thank you. I think I shall make this forum my home.
I had tried changing the .c extension to .cpp earlier this evening but I think it caused some problems. I will mess with it some more tomorrow. Passing a struct does look like a good idea. I might even consider changing my classes to structs so that I can just pass everything in (even though I would lose the encapsulation).
On a different note, would it be wise or even possible to pass a void pointer to the market object into the event_update function and access the data by incrementing the pointer an appropriate amount? member functions or not, shouldn't I be able to access the heap?
Not portably. Classes may be matted, so that members are aligned to 2-byte or 4-byte units. So this:
Originally Posted by avatarofhope2
May be represented by the following memory map:
Also, virtual functions may add a pointer to either the beginning or end of the class.
I've attached the API because I would like to try to pass a class into the functions before I redesign my classes, but the code will not compile as c++ code. I discourage you from looking at the whole cpp file unless you are extremely generous and have plenty of time. Instead I ask about the first error returned when I compile twsapi.c as twsapi.cpp.
here is the code at the line under question:
twsapi.cpp(159) : error C2440: 'initializing' : cannot convert
from 'tr_contract_details::contract_details_summary *__w64 '
to 'init_contract_details::contract_details_summary *'
Types pointed to are unrelated; conversion requires reinterpret_cast,
C-style cast or function-style cast
I'm not sure whats going on here. Any ideas?
struct contract_details_summary *ds = &cd->d_summary;
That could just be that if you are compiling as *.cpp then you do not need extern "C" in the header file.
To me, it looks like there is two definitions of struct contract_details_summary, one in tr_contract_details
and one in
The compiler tries to translate one to the other, when I think you should use one and the same for both.
I could have it wrong... :)
Edit: Looking at the code, it seems like your problem is not what I described above. One possible solution is to move the struct contract_details_summary out of the struct tr_contract_details - I beleive that will solve the problem with the least amount of changes.
so in C++, designers removed the functionality to define a struct within the definition of another struct? I pulled the struct out like you suggested and I received much fewer compiler errors (5 total). one is:
i added the explicit cast (tws_instance_t *), but I'm not confident that this is a good thing to do. Why would this cast be necessary in C++ and not in C?
twsapi.cpp(813) : error C2440: 'initializing' : cannot convert from 'void *' to 'tws_instance_t *'
1> Conversion from 'void*' to pointer to non-'void' requires an explicit cast
Removing the extern "C" (and its # directives) didn't seem to do anything. I've never had to use extern before and I'm not clear on what "C" actually is. It seems like it is saying that a literal is defined in another file. What is the point of that?
To your first part: Yes, there are subtle differences between C and C++ when it comes to structure scope and such things. Since in C++ a struct and a class is esssentially the same thing, your struct definition inside a class/struct becaomes a "local" definition. If you really want the struct to be inside your other struct, you could prefix it with "outer_struct_name::inner_struct" [can't be bothered to look up the exact names in your case].
Originally Posted by avatarofhope2
Second piece: void * is compatible with all pointers in C, but C++ doesn't allow the assignment of struct type pointers [again, because it's essentially a class] directly from a void *, because you may in this case bypass the constructor - you should use new to allocate new data and objects according to the design of the language. If it's a plain data structure, it is of course fine to just cast it.
Third piece: the construction extern "C" tells the compiler that "the following piece is not C++ standard, but C". It has little to do with "extern" in the sense of "this function is somewhere else and not in this object file".
I think I have sufficiently resolved the previous problems, but I have a new compiler error that I have never seen before. If anyone here has seen something like this error and has any insight into its cause, I would appreciate advice.
it looks like it is trying to make a copy of a market object in receive_tick_price().
twsapi.obj : error LNK2019: unresolved external symbol
"public: __thiscall market::market(class market const &)"
(??0market@@QAE@ABV0@@Z) referenced in function
"void __cdecl receive_tick_price(struct tws_instance *)"
It looks like you declared a copy constructor for market, but the linker could not find the implementation.
This can happen for several reasons. Perhaps you forgot to implement that function. Maybe you implemented it in a source file but forgot to add that source file to your project/makefile/command line. Maybe you implemented that function but forgot to add the market:: to the front so the compiler knew it was a member function of the market class. Maybe you meant to disable copying of market but made the copy constructor public instead of private so that receive_tick_price has access to the declaration.
If you can't find the problem, show the declaration of the copy constructor inside market and the code that implements the copy constructor function as well.
hurray thank you. it successfully compiled. I had a copy constructor prototype but no definition because I thought I would get the default copy constructor. apparently I was misinformed
Originally Posted by Daved
If you want the default copy constructor (which you often do), then just remove the prototype. Some people recommend leaving a comment in its place that states that the default copy constructor is appropriate.
Same goes for the copy assignment operator and the destructor.