Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Change /Call TFrame Fields & methods created from Dll in Host App


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: May 23, 2016 2:04 PM Last Post By: Ahmed Sayed
Ahmed Sayed

Posts: 173
Registered: 8/9/07
Change /Call TFrame Fields & methods created from Dll in Host App  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 22, 2016 11:27 AM
Hi,

This is deriving me crazy actually because i am pretty sure
that i have done it before but somehow it is giving me a lot
of errors and exceptions and i have no idea why?

Before i start just wanna make sure that i am compiling both
host application and dll with Run-time packages so i have no
issues for the TFrame to appear on the form or its parent control
whatever it is.

Here is the code for the dll:
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
 
#include <vcl.h>
#include <windows.h>
#include <Vcl.Controls.hpp>
#include "Frame2U.h"
 
#pragma hdrstop
#pragma argsused
 
#define DLLEXPORT __declspec(dllexport) __stdcall
 
TApplication *ThisApp = NULL;
 
extern "C" {
//---------------------------------------------------------------------------
TDllFrame* DLLEXPORT CreateDllFrame(HWND CallingApp, TStrings *Params, TWinControl* ParentControl)
{
if (!ThisApp)
	{
	ThisApp = Application;
	Application->Handle = CallingApp;
	}
 
TDllFrame* Frame = new TDllFrameTest(ParentControl);
Frame->Params = Params;
Frame->Parent = ParentControl;
return Frame;
}
//---------------------------------------------------------------------------
TComponentClass DLLEXPORT GetFrameClass(HWND CallingApp)
{
if (!ThisApp)
	{
	ThisApp = Application;
	Application->Handle = CallingApp;
	}
 
RegisterClassW(__classid(TDllFrameTest));
 
return __classid(TDllFrameTest);
}
//---------------------------------------------------------------------------
TFrame* DLLEXPORT GetSimpleFrame(HWND CallingApp, HWND ParentControl)
{
if (!ThisApp)
	{
	ThisApp = Application;
	Application->Handle = CallingApp;
	}
TFrame* Frame = new TFrame(Application);
Frame->ParentWindow = ParentControl;
SetParent(Frame->Handle, ParentControl);
return Frame;
}
//---------------------------------------------------------------------------
}
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if (reason == DLL_PROCESS_DETACH)
	{
	if (ThisApp)
		Application = ThisApp;
	}
	return 1;
}


And here is my Host App Code:

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
if (ParamCount() > 0)
	{
	HINSTANCE DllLib;
 
	LoadDll(DllLib, ParamStr(1));
 
	if (DllLib)
		{
		TCreateDllFrame CreateDllFrame = (TCreateDllFrame)GetDllFunc(DllLib, "CreateDllFrame");
		TStringList *Params = new TStringList;
 
		if (CreateDllFrame)
			{
			TDllFrame* Frame = CreateDllFrame(Application->Handle, Params,Panel1);
 
			//raises an error here every time
			Frame->Align = alClient;
			//or here
			Frame->Connection = "Some Text";
			}
		}
	}
}
//---------------------------------------------------------------------------


My Frames code are like this:

//TDllFrame
 
//---------------------------------------------------------------------------
 
#ifndef DllFrameUH
#define DllFrameUH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TDllFrame : public TFrame
{
__published:	// IDE-managed Components
private:	// User declarations
TStrings *FParams;
UnicodeString FConnection;
protected:
//Setters/Getters
virtual void __fastcall SetParams(TStrings *Value);
public:		// User declarations
	__fastcall TDllFrame(TComponent* Owner);
//Fields/Properties
__property TStrings *Params = {read = FParams, write = SetParams};
__property UnicodeString Connection = {read = FConnection, write = FConnection};
};
//---------------------------------------------------------------------------
#endif
 
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "DllFrameU.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
__fastcall TDllFrame::TDllFrame(TComponent* Owner)
	: TFrame(Owner)
{
Align = alClient;
}
//---------------------------------------------------------------------------
void __fastcall TDllFrame::SetParams(TStrings *Value)
{
FParams = Value;
}
//---------------------------------------------------------------------------
 
 
//TDllFrameTest 
 
//---------------------------------------------------------------------------
 
#ifndef Frame2UH
#define Frame2UH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include "DllFrameU.h"
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TDllFrameTest : public TDllFrame
{
__published:	// IDE-managed Components
	TButton *Button1;
	TMemo *Memo1;
	TEdit *Edit1;
	TCheckBox *CheckBox1;
	TListBox *ListBox1;
	TColorBox *ColorBox1;
private:	// User declarations
public:		// User declarations
	__fastcall TDllFrameTest(TComponent* Owner);
};
//---------------------------------------------------------------------------
#endif
 
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Frame2U.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "DllFrameU"
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
__fastcall TDllFrameTest::TDllFrameTest(TComponent* Owner)
	: TDllFrame(Owner)
{
}
//---------------------------------------------------------------------------
 


So there is nothing special for the 2 frames

Now, Why am i getting this error for setting a property? Do i have to do something special for these property to work properly?

--
The limits of my language mean the limits of my world
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Change /Call TFrame Fields & methods created from Dll in Host App  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 11:31 AM   in response to: Ahmed Sayed in response to: Ahmed Sayed
Ahmed wrote:

This is deriving me crazy actually because i am pretty sure that i
have done it before but somehow it is giving me a lot of errors and
exceptions and i have no idea why?

What are the actual errors/exceptions you are seeing?

TFrame* Frame = new TFrame(Application);
Frame->ParentWindow = ParentControl;
SetParent(Frame->Handle, ParentControl);
return Frame;

Why are you calling SetParent() manually?

TDllFrame* Frame = CreateDllFrame(Application->Handle,
Params,Panel1);

Did you verify that CreateDllFrame() is returning a valid TDllFrame object?

//raises an error here every time
Frame->Align = alClient;
//or here
Frame->Connection = "Some Text";

What is the error exactly?

void __fastcall TDllFrame::SetParams(TStrings *Value)
{
FParams = Value;
}

This design is wrong. Your TDllFrame constructor should be creating a new
TStringList, and then SetParams() should be calling FParams->Assign() to
make a copy of the input TStrings data. Otherwise, you are taking ownership
of the caller's TStrings object itself, which is bad. This also means that
the TForm1 constructor needs to destroy the TStringList it creates, don't
assume CreateDllFrame() will take ownership of it.

Now, Why am i getting this error for setting a property?

What error exactly?

--
Remy Lebeau (TeamB)
Ahmed Sayed

Posts: 173
Registered: 8/9/07
Re: Change /Call TFrame Fields & methods created from Dll in Host App  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 12:06 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
When i run the dll as a parameter to host app i get the following
error and that Dll project wants me to point it to "MainU.cpp" file
which contains the actual error, and when i do it highlights that line with red:

Frame->Connection = "Some Text";
 
//Here is the error i am getting from the dll
 
//First chance exception at $50061D8E. Exception class 
//$C0000005 with message 'access violation at 0x50061d8e: 
//write of address 0x00130180'. Process HostApp.exe (6012)


The weird thing is i had this problem before in an older project
and i am pretty sure that i fixed it but i don't have source files anymore.

As i remember but i am not sure it was something with how i
get the procedure from the dll instance or something like i can't
recall what it was?

--
The limits of my language mean the limits of my world
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Change /Call TFrame Fields & methods created from Dll in Host App[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 12:18 PM   in response to: Ahmed Sayed in response to: Ahmed Sayed
Ahmed wrote:

When i run the dll as a parameter to host app i get the following
error and that Dll project wants me to point it to "MainU.cpp" file
which contains the actual error, and when i do it highlights that line
with red:

Frame->Connection = "Some Text";
//Here is the error i am getting from the dll
 
//First chance exception at $50061D8E. Exception class //$C0000005
with message 'access violation at 0x50061d8e: //write of address
0x00130180'. Process HostApp.exe (6012) 

Well, then clearly you are not accessing a valid TDllFrame object pointer.
Have you tried stepping into the DLL code with the debugger?

--
Remy Lebeau (TeamB)
Ahmed Sayed

Posts: 173
Registered: 8/9/07
Re: Change /Call TFrame Fields & methods created from Dll in Host App[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 12:51 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Yes i tried and the debugger moves in that sequence by
highlighting each of the following lines.

Frame->Connection = "Some Text";
Application->ShowException(&exception);
 
//Then exits the program


I check if got a valid TDllFrame like this:

TDllFrame* Frame = CreateDllFrame(Screen, Application, NULL,Panel1);
 
if (Frame != NULL)
	{
	Frame->Parent = Panel1;
	Frame->Align = alClient;
	//Error here
	Frame->Connection = "Some Text";
	}


So if the TDllFrame object pointer was not valid it shouldn't have
raised any errors.

--
The limits of my language mean the limits of my world
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Change /Call TFrame Fields & methods created from Dll in HostApp[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 1:03 PM   in response to: Ahmed Sayed in response to: Ahmed Sayed
Ahmed wrote:

Yes i tried and the debugger moves in that sequence by highlighting
each of the following lines.

Frame->Connection = "Some Text";
Application->ShowException(&exception);
//Then exits the program

That is not what I meant. Did you use the debugger to actually look at the
TDllFrame object that is being pointed at, to make sure its content looks
sane? If it does not look right, then you have a bad pointer.

I check if got a valid TDllFrame like this:

No, you are only checking to make sure you have a non-NULL pointer. That
is not the same thing as making sure you have a valid pointer to a valid
object.

TDllFrame* Frame = CreateDllFrame(Screen, Application, NULL,Panel1);

Those are not the same parameters you showed earlier. What have you changed
since you started this discussion?

So if the TDllFrame object pointer was not valid it shouldn't have
raised any errors.

Not true.

--
Remy Lebeau (TeamB)
Ahmed Sayed

Posts: 173
Registered: 8/9/07
Re: Change /Call TFrame Fields & methods created from Dll in HostApp[Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 23, 2016 2:04 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
This is the new code:

//Dll code
 
#include <vcl.h>
#include <windows.h>
#include <Vcl.Controls.hpp>
#include "Frame2U.h"
 
#pragma hdrstop
#pragma argsused
 
#define DLLEXPORT __declspec(dllexport) __stdcall
 
TApplication *ThisApp = NULL;
TScreen *ThisScr = NULL;
 
extern "C" {
//---------------------------------------------------------------------------
TDllFrame* DLLEXPORT CreateDllFrame(TScreen *HostScr, TApplication *CallingApp, TStrings *Params, TWinControl* ParentControl)
{
if (!ThisApp)
	{
	ThisApp = Application;
	Application = CallingApp;
	}
 
if (!ThisScr)
	{
	ThisScr = Screen;
	Screen = HostScr;
	}
 
TDllFrame* Frame = new TDllFrameTest(Application);
Frame->Params = Params;
Frame->Parent = ParentControl;
Frame->Visible = true;
return Frame;
}
//---------------------------------------------------------------------------
 
//Host app
 
CreateDllFrame = NULL;
 
if ((CreateDllFrame = (TCreateDllFrame*)GetProcAddress(HInstance,"CreateDllFrame")) == NULL)
	{
	ShowMessage("Function not found!");
	}
else
	{
	TDllFrame* Frame = (TDllFrame*)CreateDllFrame(Screen, Application, NULL,Panel1);
 
	if (Frame != NULL)
		{
//				Frame->Parent = Panel1;
//				Frame->Align = alClient;
		//Error here
		Frame->Connection = "Some Text";
		}
	}
 


I think I know where is the problem.

The error was only raised when used the host app
code in the Form constructor/OnCreate/OnShow
but when i used it in a button click it worked very
well. But i still don't what was the problem with creating
the frame so early in the application startup.

--
The limits of my language mean the limits of my world
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02