|
Hello,
If am correct a DLL can access member functions of an application (.EXE)if the implementation is done within the header file (.h) and not within the .cpp. Something like inline functions.
Doing so may oblige us to make the source code visible since the header must be supplied with the application.
So my question is how to do to avoid this and to make visible only the declaration of the functions.
Many thanks for your kind help.
|
|
|
|
|
one way to handle this is with what's known as the "PIMPL" pattern.
PIMPL[^]
there are many many ways to implement it.
one way is with an abstract base class.
share the abstract base class header, which defines the public interface, and includes a "create" function.
then your implementation inherits from that base class.
exported .h
class baseClass
{
virtual int doCalc() = 0;
};
extern baseClass * createDerived();
private .h
class derivedClass : public baseClass
{
virtual int doCalc();
};
.cpp
baseClass * createDerived()
{
return (baseClass *) new derivedClass();
}
int derivedClass::doCalc()
{
return 9;
}
or, with more of a C interface, using a 'handle' paradigm:
.h
typedef void * myClassHandle;
extern myClassHandle createObject();
extern int doCalc(myClassHandle hnd);
.cpp
myClassHandle createObject()
{
return (myClassHandle) new myClass();
}
int doCalc(myClassHandle hnd)
{
myClass * p = (myClass*)hnd;
return p->doCalc();
}
etc..
basically, you put a layer between your class and the caller.
|
|
|
|
|
In general you'll also export some kind of deleteObject function to avoid mixing heaps.
Steve
|
|
|
|
|
|
I've already given you a solution... if you only want to pass data back and forth, use data structures instead of passing pointers to classes.
|
|
|
|
|
Albert,
Thank you very much your help.
Actually I also want the DLL calls the application's functions.
So the idea was to pass a reference or a pointer of the class containing the functions.
and to call the functions with that object from within the DLL.
I do not know well how work structures. Do you mean that I can do so with a structure without being obliged to put the implementation of the functions in the header file?
|
|
|
|
|
I meant forget about calling functions from your DLL to your main application.
|
|
|
|
|
There is no point of having a DLL if it needs to call back into the application in this way. You would be better just adding the source functions into your application project.
The best things in life are not things.
|
|
|
|
|
Export function from exe and import in dll.
Below example is taken from http://www.codeguru.com/cpp/w-p/dll/article.php/c3649
In the EXE:
// Do exactly as you would export a DLL...
extern "C"
{
EXPORT void ExeFn(char * lpszMessage)
{
MessageBox(NULL,lpszMessage,"From Exe",MB_OK);
}
}
In the DLL:
...
// Get the handle of the EXE that loaded us.
FnPtrT FnPtr = (FnPtrT)::GetProcAddress(GetModuleHandle(NULL),
"ExeFn");
if(FnPtr)
(*FnPtr)("Message From The DLL");
else
MessageBox(NULL,"It Did Not work ,"From DLL",MB_OK);
...
|
|
|
|
|
I posted a question on here a few days ago and got a great deal of help. Hopefully someone will be able to help me again.
Some quick background: I've got very little experience with C++ and was thrown into a job that needed some custom application for a client's scanner. My background is in web development, so I may explain something incorrectly now and then.
Much of the code I'm working with is from the Canon CapturePerfect SDK.
The error I'm receiving is
error C3641:
The line causing this error reads:
int WINAPI CpCallBackFunc( int, WPARAM, LPARAM, DWORD );
The line is in a header file attached to the main document. Is there a way to adjust this so that the program will still run with clr:pure, or a clr support setting that will allow the function to compile without changing everything else? The project so far has been coded with clr:pure.
|
|
|
|
|
Thought the whole idea with clr:pure was to promise that you didn't performed calls into the native non-managed world.
I would probably move the logic calling the native CpCallBackFunc() into a seperate DLL compiled with just /clr. Then call this DLL from the clr:pure part.
You would then have to compile an x86 and an x64 of the DLL with the native calls
Alternative just change from clr:pure / clr:safe into standard clr.
|
|
|
|
|
I'm new to c++ so I'm not exactly sure how to go about attaching a DLL, or what exactly I'd put into the DLL.
I did adjust the CLR from pure to standard, it only produced more errors. I checked the sample of the API I have from Canon and noticed it had no clr.
When I change my project to have no clr, I received 4 errors.
"fatal error C1852: Printer_Application.pch"
Got the error 4 times on 4 separate files. Is there a solution to this?
|
|
|
|
|
if my OS use Classic theme, can I use XP theme only for my app, without affecting other windows?
|
|
|
|
|
|
The user chooses the theme. Why should your application ignore the users preference?
Many people with visual impairments use Classic themes to improve the read-ability of the screen. People with severe colorblindness use the High Contrast themes, which are based on the classic theme.
My suggestion is to not force your style on the user if they have choosen not to use themes.
/* Charles Oppermann */
http://weblogs.asp.net/chuckop
|
|
|
|
|
Since I found this site, it has helped me improve my skills a lot.
I used to ask about MFC but now I need to know the relevancy between virtual inheritance and polymorphism.
I tried to find it in Google, but I couldn't find what I'd like to know.
Maybe I think it's because virtual inheritence is only used for multiple inheritance, which is considered bad to use.
For example, it seems like there is no way to keep polymorphism the way I think it has to be in multiple and virtual inheritance, as you see below.
class A{};
class B : public A{};
class C : public A{};
class D : public B, public C{};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new D(); }
This seems like a very reasonable compile error to me but why?
Is it not an IS-A relationship? I'd like to thoroughly understand this.
Also, as you can see in the code below,
class A{};
class B : public A{};
class C : public A{};
class D : public B, public C{};
int _tmain(int argc, _TCHAR* argv[])
{
B* b = new D(); }
If A and D are not an IS-A relationship, why does B and D have to be an IS-A relationship?
Or something like this.
class A{};
class B : public A{};
class C : public A{
public:
virtual void Func(){
cout << "Called??";
}
};
class D : public B, public C{
public:
virtual void Func(){
cout << "Called!!";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
B* b = new D();
b->Func(); }
I understand that I can figure out how this works, but since it's a pretty complicated thing, I'd like to know why this happens, THROUGHLY.
So I'd like to know where on the internet web pages I can figure all this out so that I can sleep tight!
Thanks in advance.
modified on Tuesday, August 2, 2011 2:13 AM
|
|
|
|
|
Just a partial answer...
In your first case, the compiler (along with all us humans ) doesn't know whether the A* should point to an instance of A->B->D or an A->C->D, in other words whether to use A, B and D constructors, or A, C and D. It's a bit hard to see here, but a more complex (subtle) example could show the difference, in terms of class members (fields or methods) unique to B or C.
In your second case (that works), this ambiguity doesn't exist.
Clear as mud, I know, but OOP is like that.
Cheers,
Peter
Software rusts. Simon Stephenson, ca 1994.
|
|
|
|
|
|
The first one is a clear case of Diamond Inheritance Problem, As there will be two copies of A in B & C , the compiler will be confused which one to use for D. This is where virtual inheritance steps in.
Refer http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8[^] for a start.
"Every morning I go through Forbes list of 40 richest people in the world. If my name is not in there, I go to work..!!!"
|
|
|
|
|
The compliler has no problem in creating the D object with two A-s in it.
The problem is the assignment to the A* (that is ambiguous since there are two of them), not the D creation.
2 bugs found.
> recompile ...
65534 bugs found.
|
|
|
|
|
|
|
|
|
Peter has already given a partial answer to your question.
just consider the below example
class A
{
public:
A()
{
cout << "A::A\n";
}
};
class B : public A
{
public:
B()
{
cout << "B::B\n";
}
};
class C : public B
{
public:
C()
{
cout << "C::C\n";
}
};
int main()
{
A* a = new C();
return 0;
}
What will be the output
A::A
B::B
C::C
right??
means the order of object creation is like A->B->C
and C objects reference is being put into A's pointer
In your code
There are two object creation order
like A->B->D
and
like A->C->D
Here compler would be confused which D's reference comes to A's pointer???
That is why there is compilation error. c++ provides us something through which we can overcome this problem. Thats the virtual class.
You might have heard of diamond problem in c++. This what happens here.
you can change you code like below.
class A{};
class B : virtual public A{};
class C : virtual public A{};
class D : public B, public C{};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new D();
}
note the key word virtual.
Now the order of object creation will be like A->B->C->D. you can print some thing in constructure of each class and can see this.
In the second code snippet
class A{};
class B : public A{};
class C : public A{};
class D : public B, public C{};
int _tmain(int argc, _TCHAR* argv[])
{
B* b = new D();
}
There is no confusion for the compiler even though there are 2 object creation order.
One like A->B->D and another like A->C->D. But you have clearly mentioned that D objects refernce goes to B's pointer.
So complier will take A->B->D order and put this into B's pointer. But C object also will be created.
Now it is clear that why the third code snippet cause an error.
B's pointer stores a reference of D object being created in the order A->B->D. There is no Func() function on the way. Is there??
|
|
|
|