|
The trick I've described in previous post would work. The only prerequisite is that objects in the list are derived from class defined in .dll.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
Ahh, I think I get it.
Yes, all the custom objects are derived from a base class that's in the DLL.
So, You're saying that I can just override the ::delete operator in the base class. That way the object is always deleted from the DLL?
Is that correct?
|
|
|
|
|
SchmoBoy wrote:
You're saying that I can just override the ::delete operator in the base class
Actually, I wasn't referring to this solution. I'm not sure if you can achieve your goal with overriding delete operator (note that you'd have to override new as well). Give it a try, if it's not possible, consider the following:
I'd add special abstract method in base class:
class BaseClassInDll
{
public:
...
virtual void DeleteMe() = 0;
};
Your list would call obj->DeleteMe() instead of delete obj. Users of your .dll would have to provide the implementation of DeleteMe. Implementation is trivial, it's just 'delete this' statement:
class DerivedInExe : public BaseClassInDll.
{
public:
...
virtual void DeleteMe() { delete this; }
};
Basically, this provides sort of callback into EXE available from DLL.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
Well, Tomasz headed me in the right direction...
The solution is to overload the ::new and ::delete operators so ALL memory allocation and deallocation are routed through the DLL. In the base class I simply added the following functions. Note the three parameter new and delete are required as MFC uses these calls for tracing, etc. So I just included both to work with and without MFC/Win32.
<br />
void * CMPI_Obj::operator new(size_t sizeofRow)<br />
{<br />
void* p = new char[sizeofRow];<br />
<br />
return memset(p, 0, sizeofRow * sizeof(char));<br />
} <br />
<br />
void * CMPI_Obj::operator new(size_t sizeofRow, LPCSTR lpszFileName, int nLine)<br />
{<br />
void* p = new char[sizeofRow];<br />
<br />
return memset(p, 0, sizeofRow * sizeof(char));<br />
} <br />
<br />
void CMPI_Obj::operator delete(void *ptr)<br />
{<br />
::delete ptr; <br />
}<br />
<br />
void CMPI_Obj::operator delete(void* ptr, LPCSTR lpszFileName, int nLine)<br />
{<br />
::delete ptr; <br />
}<br />
<br />
Thanks for everyone's help and suggestions. I think I've found the most elegant solution where we can still JUST ship RELEASE and the customer can still build DEBUG against it.
|
|
|
|
|
I don't have any reference book at hand right now, but make sure you have operator new for arrays as well.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
Yes, you are correct. new[] and delete[] are needed. I forgot those in the code snippet above.
|
|
|
|
|
could you make them provide a callback function for your DLL to use that would handle de-allocation?
ie. they write a function that like this:
BOOL CALLBACK MyFree(Object *p)
{
delete p;
return TRUE;
}
and your code would do:
// time to delete this
(*CallerFree)(pObject);
that way, the delete used will always be the correct one.
-c
Aiei i ea eio aoa i e eio e aigoa
|
|
|
|
|
Chris Losinger wrote:
Aiei i ea eio aoa i e eio e aigoa
"Yesterday was oil now it is oil and water"
Anche tu parla Spezzino ?!
Concussus surgo.
When struck I rise.
|
|
|
|
|
Daniel Turini wrote:
Anche tu parla Spezzino ?!
no
i just like the fact that the sentence has only one consonant.
-c
Aiei i ea eio aoa i e eio e aigoa
|
|
|
|
|
we had the same issues
My solution was to release 2 forms of the lib both with the .lib and .dll files
The first was the standard release build
the second was a "fake" debug build,
in the C++ settings it had Optimizations turned on, and Debug info turned off. BUT in the COde Generation setion it used the Debug Multithreaded DLL libs as opposed to the Multithreaded DLL libs. The linker settings were the same as release - i.e. no debug info
This seemed to do the trick
If this is wrong please don't shoot me
|
|
|
|
|
I am attempting to create a doc/view application with dialog boxes. On startup, I am looking to launch a dialog box, once the view is created, to collect some information. I can easily create a function in the menu to do this, but I'd rather the dialog box launch automatically. How do I do this?
Thanks in advance.
|
|
|
|
|
Launch the dialog at the end of OnInitialUpdate.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
I tried to launch the dialog box at the end of OnInitialUpdate, in the View class, but it does not create the view first. Is there a function that is processed after the view and the doc class are created, as if a user selected FILE->LAUNCH? Thanks again for the comment.
Rich
|
|
|
|
|
Well, technically speaking the view is created, but its frame isn't visible at this moment. If you need to show dialog when view is visible, call PostMessage (not SendMessage!) in OnInitialUpdate and provide handler for appropriate command in CYourView:
void CYourView::OnInitialUpdate()
{
...
PostMessage(WM_COMMAND, ID_SHOW_YOUR_DIALOG);
}
ID_SHOW_YOUR_DIALOG may appear in menu as well. Messages posted with PostMessage are going through message queue and will be processed after view initialization ends.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
What I need to do is to install ODBC DSNs while installing my main application.
I am trying to use the CallDLLFx function of InstallShield to do this - the DLL has one function that installs the DSNs which InstallShield can call.
My function declaration is
static LONG APIENTRY CreateApplicationDSN(HWND hWnd,LPLONG lplValue,LPSTR lpszValue);
My CallDLLFx in InstallShield looks like this:
<br />
function SetupODBCDrivers()<br />
<br />
STRING szDll;<br />
STRING szFunction;<br />
LONG lValue;<br />
STRING svValue;<br />
LONG lResult;<br />
<br />
begin<br />
szDll = TARGETDIR ^ "ConfigAppODBC.dll";<br />
szFunction = "CreateApplicationDSN";<br />
svValue = "";<br />
lValue = 0;<br />
lResult = CallDLLFx ( szDll , szFunction, lValue, svValue );<br />
<br />
if(lResult = 0 || lResult = 1)<br />
then<br />
return lResult;<br />
else<br />
return -1;<br />
endif;<br />
end;<br />
<br />
I consistently get a -1 from this function. The DLL function ConfigAppDSN returns a 0 or a 1 based on a successful install or not.
What am I doing wrong. One thing I do know is that I do not have the ConfigAppDSN function in the .DEF file. When I do put it there, I get a linker LINK2001 error.
Thanks
ashish
|
|
|
|
|
From what I remember (back in 1999), CallDLLDx lets you call a DLL function but you must respect rules for the function. I believe you have a topic in InstallShield doc that tells you what is the signature of the outside function you call. In other words, I believe you need to have an intermediate DLL exporting an entry-point function with a known signature. And this DLL will do ::LoadLibrary("configappodbc.dll") and ::GetProcAddress...
And I swallow a small raisin.
|
|
|
|
|
Ok, after the first day back to school I am working on a little app, which is an assignment. I am not asking for anyone to do it for me, however this error doesn't make sense to me. Here is the contents of my header file:
#ifndef HW1_H
#define HW1_H
#include <fstream.h>
#include <iomanip.h>
#define ListOfDivers "divers.dat"
#define OutputFile "output.dat"
#define ReportFile "report.dat"
const int Total_Divers = 24;
const int Best_Divers = 12;
const int Num_Of_Dives = 10;
const int Num_Of_Scores = 7;
struct Dive_Stats
{
float difficulty;
float scores[Num_Of_Scores];
};
struct Diver_Info
{
char Diver_Name[80];
Dive_Stats Dives[Num_Of_Dives];
float Total_Score;
};
void Input_Data(Diver_Info []);
void Calculate_Totals(Diver_Info []);
void Create_Report(Diver_Info []);
void Sort_Divers_Scores(Diver_Info []);
void Create_Output(Diver_Info []);
#endif
When I am compiling I get several errors that point to my two structures. The first error points to
float scores[Num_Of_Scores];
saying error C2057: expected constant expression . Does that make sense??
Thanks for any tips.
Nick Parker
|
|
|
|
|
Not sure, but why do you have 2 empty includes at the top with no headers specified?
|
|
|
|
|
that's a problem with the CP boards, not Nick's code.
Aiei i ea eio aoa i e eio e aigoa
|
|
|
|
|
|
|
I think I found the error, I was just trying to compile the .C files in VS, which caused it to flake out because of my syntax, thanks guys.
Nick Parker
|
|
|
|
|
C++ on a unix box, so he has asked us to use a .C extension. When I try this on VS and save my two .C files as .cpp I still get the same errors. The two structures themselves appear to be in the correct format, I have no idea why it is telling me that I need a constant expression there.
Nick Parker
|
|
|
|
|
So apparently the compiler decided it's a C program. In C you'll need to #define your constants. While language allows const modifier for variables, you can't use them as size of array (and, generally speaking, wherever you need a value known at compile time).
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
GCC 3.2 warns about the deprecated fstream.h header, but the structure declarations don't cause any errors.
|
|
|
|