Resource Synchronization with a LoadLibrary

Dear Experts ,
I'm trying to design the following architecture :

Client DLL -> Factory DLL -> Provider DLL

The client DLL  is an MFC C++ DLL that containts a LoadLibrary on the Factory DLL.

The Factory DLL only create an instance of the Provider DLL objects and returns a pointer to that new object. then the client use that pointer to call different method in the Provider.DLL object.

when I call a method of the Provider DLL object , it works but as soon as the this object does a loadstring in the string table I get an ASSERT in the AfxGetResourceHandle.  What do I need to do to synchronize the resource between th modules?


Client DLL:
void C2020XmlData::SifXml()
{	
	HINSTANCE hDll;
	hDll = LoadLibrary(_T("Factory.dll"));//
	LPFNDLLFUNC1 testToTo;
	bool bIsOk = FALSE;
	
	if(hDll != NULL)
	{
		AfxSetResourceHandle(hDll); 
		testToTo = (LPFNDLLFUNC1)GetProcAddress(hDll, "DllGetObject");
 
		if(testToTo != NULL)
		{
			ISifCatalog* pMyObject = (testToTo)();
			if(pMyObject != NULL)
			{
				CString scatName("D:\\Repository\\als\\A32\\A32.top");
				pMyObject->SetWriteMode(1);	 
				pMyObject->SetFileCatName(scatName);
				pMyObject->SetremoveNulPrice(true);
				pMyObject->SetremoveNulDimensions(true);
				pMyObject->SetremoveNulDescription(true);
				pMyObject->SetremoveIdenticalPO(true);
				pMyObject->SetpushOptionPriceToProduct(true);
				pMyObject->SetwriteIgnoredSifCodes(true);
 
				pMyObject->Read();
 
				AfxMessageBox("Done !!!!");
				FreeLibrary(hDll);
		
			}
			
		}
		
	}
}
 
Factory DLL:
 
extern "C"
__declspec(dllexport) ISifCatalog* DllGetObject()
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	ISifCatalog* pObj = static_cast<ISifCatalog*>(new SifCatalog);
	return pObj;
}
 
Provider object contain method that are called in the Client Object.

Open in new window

toy187Asked:
Who is Participating?
 
itsmeandnobodyelseConnect With a Mentor Commented:
>>>>> AfxSetResourceHandle(hDll);

The AfxSetResourceHandle would be used if you want to access resources which were built with that dll where the hDll is the instance handle of.

E. g. if you have a x.dll which has a resource file x.rc, and have y.exe which loads the x.dll with hxdll = LoadLibrary, then after calling AfxSetResourceHandle(hxdll), the y application could load strings from the x.rc.

As far as I see, you have a far different case above:

- the client dll loads the factory dll
- the factory dll loads the provider dll statically
- the client dll resets its resource handle by calling AfxSetResourceHandle
- an exported method in the provider dll calls LoadString

Obviously, the last call cannot access a resource loaded with the factory dll as each dll has its own resource handle. Or differently said, when you call AfxSetResourceHandle in the client dll, it has *no* influence on the resource handle stored in the provider dll. If you want to change that, you need to provide a method in the provider dll where you can pass a different handle and where the method in the provider dll calls AfxSetResourceHandle. Note, I don't say that this would work, as the Afx methods partially rely on static and global variables which can't be exchanged between executables. A much better approach is to have a common resource dll whcih was loaded by all dlls and where each dll calls the AfxSetResourceHandle separately (and independently).

Regards, Alex
0
 
mahesh1402Commented:
How you are loading string resource from DLL ?What you need to do here is temporarily set the resource handle of your resource DLL as current, and then call LoadString and then restore resource handle.

e.g.


 HINSTANCE    hOldInstance = AfxGetResourceHandle();
 AfxSetResourceHandle( hMyResourceDllInstance );


 CString strTest;
 strTest.LoadString( IDS_MY_EXTERNAL_RESOURCE_STRING );


 AfxSetResourceHandle( hOldInstance );

--How are you loading ???

-MAHESH
0
 
jkrCommented:
I'd rather try to access the strings by specifying the module instance directly to minimize the confusio of MFC's chained resource list, i.e. instead of using a CString helper, use the Win32 API:
char buffer[255];
 
::LoadString(hDll,IDS_MYSTRING1,buffer,255);

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
toy187Author Commented:
thank you all for your comments , the thing is that the module that  does the loadstring is part of another MFC application that works , I can't modify the way it load the resource. After doing some testing , I realize that I don't have the assert with a new and empty MFC application in which I call my object the same way. The module in which I'm trying to create this is loaded in a mfc app with  the ATL Class Factory. Maybe there is something to be done in my new imported module in order to sychronize the resources?
0
 
jkrCommented:
What asseretion (file, line) exactly are you getting?
0
 
toy187Author Commented:
It is asserting in the  C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\afxwin1.inl
line 26
 _AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle()
       { ASSERT(afxCurrentResourceHandle != NULL);

So clearly the current Ressource Handle is null even though I did the  AfxSetResourceHandle(hDll); and the AFX_MANAGE_STATE(AfxGetAppModuleState());
0
 
jkrCommented:
Is 'C2020XmlData::SifXml()()' called directly also or only via the constructor?
0
 
DanRollinsCommented:
Perhaps more succinctly:  It appears that you need to make changes in the Provider DLL.   Is that possible?

In particular, it appears that the Provider DLL does not do the normal setup that would initialize the global value of afxCurrentResourceHandle.
0
All Courses

From novice to tech pro — start learning today.