|
You could get your users to build in release mode but use debugging info in their app so its almost the same as regular debugging.
Roger Allen
Sonork 100.10016
I think I need a new quote, I am on the prowl, so look out for a soft cute furry looking animal, which is really a Hippo in disguise. Its probably me.
|
|
|
|
|
i'd never use a library that made me do that.
-c
Aiei i ea eio aoa i e eio e aigoa
|
|
|
|
|
Well, its only a suggestion.
Roger Allen
Sonork 100.10016
I think I need a new quote, I am on the prowl, so look out for a soft cute furry looking animal, which is really a Hippo in disguise. Its probably me.
|
|
|
|
|
do your customers have to use the objects allocated inside your DLL? some of my DLLs allocate objects and pass them back to the caller, but the caller never has to do anything with the object, except pass it back into the DLL. also, i always pass the objects back as "void *" so there's never even any temptation by the caller to do anything with the object. any manipulation and clean-up of these objects is handled by functions inside the DLL, so there's no chance of mixing debug/release code.
-c
Aiei i ea eio aoa i e eio e aigoa
|
|
|
|
|
Yes, they do.
The problem area is a custom linked list we've implemented that holds pointers to custom objects. The users allocate the custome objects then add them to the custom linked list. This custom linked list automatically cleans up the objects they allocated when the list goes out of scope.
So, they may or may not use the object that they allocate.
|
|
|
|
|
Are custom objects derived from common base class defined in your .dll? If this is the case, just add abstract Delete() method. Trivial implementation in users's code just calls 'delete this'.
Tomasz Sowinski -- http://www.shooltz.com
Free your mind and your ass will follow.
|
|
|
|
|
That's the problem. The user can't delete the object as the list does it for them. The user allocates the object, but NEVER deletes it. The list does.
|
|
|
|
|
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?
|
|
|
|