|
Hello,
I'm trying to recreate a problem that I'm having in another project and have created a small overly simple project to experiment with. That being said, I'm being blocked by what seems like a really silly problem.
So, I have two classes: ClassA and ClassB. ClassB's constructor takes a pointer to ClassA as a parameter for later use. The compiler seems not to mind that, however it does not like when I try to use the pointer that is passed. Here's some code:
#pragma once;
#include <iostream>
using namespace std;
#include "ClassB.h"
class ClassB;
class ClassA {
public:
ClassA () {
this->b = new ClassB(this);
}
void printer() {
cout << "Hello world from A!\n";
}
private:
ClassB* b;
};
And a little more:
#pragma once;
#include <iostream>
using namespace std;
#include "ClassA.h"
class ClassA;
class ClassB {
public:
ClassB(ClassA *a) {
this->ca = a;
cout << "Constructor B \n\n";
ca->printer();
}
private:
ClassA *ca;
};
and finally a main to polish it off:
#include <windows.h>
#include <iostream>
using namespace std;
#include "ClassA.h"
#include "ClassB.h"
void main() {
ClassA a;
Sleep(10000);
}
I get two errors with this setup. They both point to ca->printer(); in the ClassB.h file. They are Error 1 error C2027: use of undefined type 'ClassA' classb.h 14 and Error 2 error C2227: left of '->printer' must point to class/struct/union/generic type classb.h 14 .
Oddly enough, this isn't even the problem I'm trying to recreate from my larger project (I don't have this problem there). I'm actually trying to recreate an access violation on the call to the constructor of the class that ClassB represents (then the program continues, but it never executes the constructor).
Anyway, I'll settle for figuring out what the silly mistake I'm making is that's blocking the compiler from finishing the job.
Thanks for your help!
|
|
|
|
|
You will need to move some code into a cpp file (or two): to be able to use a pointer for a class, the compiler needs to fully know the class. In your case, both classes are referencing each other and using the pointers in the header file. It's a snake that bites its own tail.
|
|
|
|
|
Thanks for the tip, you were correct. Now I get to go back to recreating my real problem... the phantom access violation!
|
|
|
|
|
I have a x.lib and x.dll. its a static dll. Now i am using functions exported in this dll by loading this dll and calling functions thro GetProcAddress API.
Now i don't want to load dll instead i want to use x.lib, Please let me know how i can call those functions by using x.lib
|
|
|
|
|
I think you may have your terms a little confused so I'm not exactly sure what you want.
There are basically three scenarios:
1. x.dll is a Dll and is used by calling LoadLibrary and GetProcAddress
2. x.dll is a Dll, x.lib is its import library. x.lib is linked into application y which is then implicitly linked to x.dll. x.dll get loaded by y.exe during the bootstrap phase and functions in x.dll can be called directly from y.exe code, No LoadLibrary, no GetProcAddress
3. x.lib is a static library which is linked as part of y.exe. The two are merged at compile time to produce y.exe. That's it, the functions all act as if they are in the same module because they are, no LoadLibrary, no GetProcAddress
Generally you'd use:
1 if the code in x.dll is shared and only used occassionaly by y.exe
2 if the code in x.dll is shared and used all the time by y.exe
3 if x.lib is really just a subdivision of y.exe and is not used by other applications.
I hope this helps.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
I think the 2) option does work for me.
i will clarify my doubt again, please confirm whether 2) option works or not.
I have some code x when built it gives x.dll and creates x.lib.
Currently i m loading x.dll by LoadLibray and calling function thro' GetProcAddress.
Now i want to call those same functions but want to avoid using LoadLibray and GetProcAddress.
How it could be done ??
Thanks a lot !!!!
|
|
|
|
|
Yashusid wrote: How it could be done ??
You link to the .lib file.
led mike
|
|
|
|
|
OK, you need to add x.lib to the Input files list for the Linker. I'd need to know what development environment you're using to be much more specific.
Your exe source files which call functions in the dll will need to include the relevant header file from the dll source e.g.
<br />
<br />
#include "mydll.h"<br />
<br />
int iResult = MyDllFunction( "SomeString" );<br />
<br />
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
I am using VS2005.
Thanks a lot Matthew
|
|
|
|
|
In which case, as you probably know, you'll find the Linker Input files by right clicking on your project (not the solution), selecting Properties and then choosing Configuration Properties\Linker\Input in the properties dialog. You can add the name of your x.lib file to the 'Additional Dependencies'
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
Thanks ...
I have included this x.lib
Is it possible to call those function from the x.lib in y.exe application directly??
like if a function add(int,int) is implemented in x.lib ...can i call in y.exe as int n=add(2,3) ??
|
|
|
|
|
To complete what Matthew just said, if you are in scenario 2 (x.lib is the import libary of the dll), then you can't statically link to it to access the functions. The lib doesn't contain the code for the functions but only information about how to load the dll.
|
|
|
|
|
Yashusid wrote: its a static dll
impossible. DLL means DYNAMIC Link Library
|
|
|
|
|
I have create a small samle app which connects to an FTP servere and returns a list of file names and sizes in a specific folder.
The folder contains a 5+ GB file.
However the GetLength function of the CFtpFileFind class returns 0xFFFFFFFF as a size (approx 4GB). Note that I am using VS2008 and GetLength returns a ULONGLONG unlike the functions prior to MFC 7.
I created my own class using CFtpFileFind as a abse in order to see the actual WIN32_FIND_DATA used and indeed found thet the low order DWORD for the size was set to 0xFFFFFFFF and the high order DWORD was 0x00000000.
Can I deduce from this that the MFC FTP classes do not support >4GB file sizes?
|
|
|
|
|
Paul Deckers wrote: WIN32_FIND_DATA
I don't know, but if the MFC classes are causing this problem you can avoid it by using the WinInet library[^] directly. If the WinInet library is causing it then that won't help. If it is a limitation of the FTP server there is no way to solve the problem short of dividing the file into multiple files, which might not be a bad idea anyway. If the FTP Server supports it then you could find a different library or implement your own client using Sockets.
led mike
|
|
|
|
|
I have a std::list of strings which I need to pass to another function as an LPARAM, so I believe I need to create an array of char* and copy each string in but how do I create a char* array of the correct size (it says it requires a constant)? And how do I know the size of the array once they are passed to the second function? Or is there a better way to do this?
|
|
|
|
|
Something like (which might be overkill):
char **arr = new char*[l.size()];
int y = 0;
for (list<string>::iterator x = l.begin(); x != l.end(); x++)
{
string str = *x;
arr[y] = new char[str.length() + 1];
strcpy(arr[y], str.c_str());
y++;
} Now you can pass arr and l.size() as the arguments to your function.
You could also do something like:
void foo( LPARAM lParam )
{
list<string> *l = (list<string> *) lParam;
}
...
list<string> l;
foo((LPARAM) &l);
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
Thanks! That is very similar to what I had been working towards (apart from the fact it works!)
So now, in my callback I am using:
char **arr = (char**)lParam;
int count = sizeof(arr) / sizeof(*arr);
But this gives me 1 when it should be 2, what is the correct way to determine the size of the array?
|
|
|
|
|
__DanC__ wrote: But this gives me 1 when it should be 2...
Right, because a pointer is four bytes in size.
__DanC__ wrote: ...what is the correct way to determine the size of the array?
As a second argument to your function.
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
I do not have the option of a second argument to the function as it is a callback. All I can pass is the pointer as an LPARAM
|
|
|
|
|
So put the array and the count in a structure and pass the address of that structure.
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
Why don't you just pass the address of the std::list as the LPARAM? If you need a copy at the other end, copy the std::list and use the address of the copy.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
I didn't realise that was possible. How would I copy the list? I tried CopyMemory before I started down this route with no luck so decided the pointer array was probably the way to go.
|
|
|
|
|
It's a while since I've used std::list so you're probably best looking at the docs but I guess you could simply create a second std::list, then iterate through the first one, use CopyMemory or whatever for each item and then append it to the second list. I'm not sure if you can simply assign one list to another or pass the first list to a constructor of the second. I suspect it depends on what your list contains, simple POV type, complex types, pointers, etc.
Reminds me I need to look into the std containers once again. I've never really got on with them or used them on a regular basis.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
Do you really need to copy the list? Why not something like this:
void IWantAList(LPARAM lp)
{
using namespace std;
list<string> *pList = reinterpret_cast<list<string>*>(lp);
}
void SendList()
{
using namespace std;
list<string> list;
IWantAList(reinterpret_cast<LPARAM>(&list));
}
Steve
|
|
|
|