Click here to Skip to main content
15,886,061 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a structure like this

C++
#define MAX_NAME_LENGTH 40
typedef struct _tagMYPERSON  
{
    WCHAR FName[MAX_NAME_LENGTH];
    WCHAR LName[MAX_NAME_LENGTH];
    int Age;
    double Salary;
}MYPERSON;


then I have a function in a DLL like this
C++
extern "C" MARSHALDLL_API void _stdcall ModifyPersonStructArray(int nCount, MYPERSON * pPersonArr)
{
    for ( int nI = 0; nI < nCount; nI++ )
    {
	wcscat_s(pPersonArr[nI].FName, MAX_NAME_LENGTH, L"-Modified");
	wcscat_s(pPersonArr[nI].LName, MAX_NAME_LENGTH, L"-Modified");
	pPersonArr[nI].Age = pPersonArr[nI].Age+ 5;
	pPersonArr[nI].Salary = pPersonArr[nI].Salary + 1000 ;
   }
}


and This is how I call it.

C++
int nCount = 4;
MYPERSON* prsnArr = new MYPERSON [nCount];
CString strTmp;
m_lstOutput.ResetContent ();

for (int nI=0; nI<nCount ; nI++)
{
        strTmp.Format(_T("First Name %d"), nI+1);
        StringCchCopyW(prsnArr[nI].FName, MAX_NAME_LENGTH, strTmp);
	strTmp.Format(_T("Last Name %d"), nI+1);
	StringCchCopyW(prsnArr[nI].LName, MAX_NAME_LENGTH, strTmp);
	prsnArr [nI].Age = 20 + (nI+ 1)*2 ;
	prsnArr [nI].Salary = 20000 + (nI+ 1) * 1000;
	strTmp.Format(_T("Person %d=[(%s %s, Age=[%d], Salary=[%.2lf])]"), nI, prsnArr [nI].FName, prsnArr [nI].LName, prsnArr [nI].Age, prsnArr [nI].Salary);

	m_lstOutput.AddString (strTmp);
}
	  
ModifyPersonStructArray(nCount, prsnArr );
    
m_lstOutput.AddString(_T("After Call ==>"));
for (int nI=0; nI<nCount ; nI++)
{
        strTmp.Format(_T("Person %d=[(%s %s, Age=[%d], Salary=[%.2lf])]"), nI, prsnArr [nI].FName, prsnArr [nI].LName, prsnArr [nI].Age, prsnArr [nI].Salary);
	m_lstOutput.AddString (strTmp);
}


Note : m_lstOutput is a control variable (ListBox) in a MFC Dialog.

When I run in debug mode I get some error message like this,

Windows has triggered a breakpoint in MFCClient.exe.
This may be due to a corruption of the heap, which indicates a bug in MFCClient.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while MFCClient.exe has focus.
The output window may have more diagnostic information.


What I am doing wrong here ?

What I have tried:

I transferred the DLL function in the Dialog class itself. like.


C++
void CMFCClientDlg::ModifyPersonStructArray(int nCount, MYPERSON * pPersonArr)
{
    for ( int nI = 0; nI < nCount; nI++ )
    {
		wcscat_s(pPersonArr[nI].FName, MAX_NAME_LENGTH, L"-Modified");
		wcscat_s(pPersonArr[nI].LName, MAX_NAME_LENGTH, L"-Modified");
		pPersonArr[nI].Age = pPersonArr[nI].Age+ 5;
		pPersonArr[nI].Salary = pPersonArr[nI].Salary + 1000 ;
   }
}


and i have no issues. it works.

please suggest.
Posted
Updated 12-Dec-19 6:49am
Comments
Shao Voon Wong 12-Dec-19 6:57am    
Please show how you got the function pointer to that function in the dll.
Shao Voon Wong 12-Dec-19 7:26am    
Maybe your dll is outdated. Try clean and rebuild the dll project and copy the dll to the executable folder.
Praveen Kumar Katiyar 12-Dec-19 9:37am    
I did a full rebuild of all the targets. and copied the updated dll in the exe's folder, but no avail.

From the code you have posted, it appears the problem is in the declarations of the prototype versus its implementation, as Richard pointed out. I have written a LOT of DLLs and this is really not very hard. That is, to get the linkage right. I often use a header that helps with this. It looks something like this.
C++
#define DLLEXPORT __declspec(dllexport)
#define DLLIMPORT __declspec(dllimport)

// applications linking with this DLL see the import definition only

#ifdef BUILD_MY_DLL // this is defined in the DLL's project ONLY!!!
#define DLLFUNC      DLLEXPORT
#else
#define DLLFUNC      DLLIMPORT
#endif

// in a header that declares the prototype :

extern "C"
{
DLLFUNC void ModifyPersonStructArray( int count, MYPERSON * pArray );
}
Then copy that line exactly as written and paste into the implementation file of the DLL and use it as the declaration of the function. It has to match the prototype in the header EXACTLY! The last step is to define BUILD_MY_DLL in the DLL's implementation file or in its project file as a project-wide definition. This macro can NOT be defined in the application or linking will fail.

As long as the implementation code is also wrapped in the "extern C" declaration the function will be __cdecl by default so it is unnecessary. If you use it then make sure it is in both the header file and the implementation. Personally, I never use it or __stdcall unless it is required for a function used as a callback or a thread procedure.

You can also put entire classes in a DLL if you want to. This might be a case where it would be handy. You could have a function (or static method of a class) to contruct an array of the MYPERSON structures, this one to modify the array, and possibly others to do things like sorting the array and deleting it.
 
Share this answer
 
v2
Comments
Dave Kreskowiak 12-Dec-19 13:47pm    
Shouldn't that "#define BUILD_MY_DLL" be "#if BUILD_MY_DLL"??

I could be wrong. I haven't touched C/C++ in quite a long time.
Rick York 12-Dec-19 19:07pm    
Yes, it should. Thanks!
Praveen Kumar Katiyar 13-Dec-19 3:28am    
#ifdef BUILD_MY_DLL // this is defined in the DLL's project ONLY!!!

first line is not available in my (DLL's Project) header file. then I checked it, and it was defined (DLL's Project) in the Project Settings

Project Properties -> Configuration Properties -> C/C++ -> Prepreprocessor ->Prepreprocessor Definitions. (I am using VS2010 Ultimate).
Your definition in the dll export statement is incorrect. It should use the __cdecl linkage, not _stdcall. You can ensure correct linkage by using __declspec(dllexport) as described in Exporting from a DLL Using __declspec(dllexport) | Microsoft Docs[^].
 
Share this answer
 
Comments
Praveen Kumar Katiyar 12-Dec-19 5:57am    
thanks for the quick reply.

but, even changing the calling convention has no effect.

it is same.
Richard MacCutchan 12-Dec-19 6:04am    
If you have correctly implemented the proper dll linkage, and the error still occurs then you need to gather more debug information. It is impossible to guess what else is happening in your code.
It sounds like some memory issue, so first you double check the signature of your ModifyPersonStructArray function which may lead to different memory layout than wanted.

I would use some signature like this
C++
extern "C" __declspec(dllexport) ModifyPersonStructArray()
Some advanced Overview about dlls.
tip: you can debug it, when build the used dll in debug mode.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900