Sending a structure which has vector to dll function as parameter

Started by
13 comments, last by Ksaurabh.chirag 13 years, 2 months ago
Hello everyone; I have writed a dll function. It takes some paremeters and an adress of structure which includes a vector. int WINAPI ProcessFile(struct JOB_PACKET *JobPacket,struct FILE_STRUCTURE *newFileStruct ) struct FILE_STRUCTURE { int recCount; int curretRecCount; char filePath[256]; vector <struct REC_STRUCTURE> records; }; struct REC_STRUCTURE { long chipPos; int chipLen; char chName[30]; }; When I used newFileStruct and its vector of struct REC_STRUCTURE, it gives me error. here is the functions prototype : typedef int (WINAPI *ProcessFileType)( struct JOB_PACKET *, struct FILE_STRUCTURE *newFileStruct) It gives me error after going out from calling function: here is how I call it ProcessFileDll = (ProcessFileType)GetProcAddress( localJP.hPersoDll ,"ProcessFile" ); memset(&newFileStruct,0,sizeof(struct FILE_STRUCTURE)); rv = ProcessFileDll( &localJP , &newFileStruct ); How can I send a structure which has members that allocate its memory dynamically and uses member of STL library like vector ?
Advertisement
This is an extremely bad idea; you need to be absolutely sure that the EXE and DLL are built with the same STL version, which means that if you want to release your DLL, you either need to release the source so people can use it, or release lots of versions of the DLL (I can think of 4 versions offhand that you'd need at a minimum for just VC2008).
A far better idea is to avoid the use of STL objects in DLL interfaces at all.

As for the actual problem; what error do you get?
I suspect the error comes from calling memset on the struct that also contains an instance of std::vector.
In general, _don't_ call memset on anything else than POD ("plain old data"), and std::vector isn't of this kind.
The solution here is to add contrcutors / destructors to your structs.
Evil Steve : I am the programmer of same exe and dll so I think it cant be error . Function call gives memory error but actualy I cant remember which error I got because I have tried 2 days ago this function call.


plastique : Actually I have got same error on not using this memset function call. But I think that as you say using memset on STL members is a bad idea, and it is errorneous.


thanks for all ,I try another ways to do job now in 30 minute. I will give you a feedback asap.
Quote:Original post by Ahmet
Evil Steve : I am the programmer of same exe and dll so I think it cant be error . Function call gives memory error but actualy I cant remember which error I got because I have tried 2 days ago this function call.
Even so, you need to make sure you link the exact same CRT version between DLL and EXE - I.e. make sure you have debug builds of both or release builds of both, not mixing and matching.

I'd still highly recommend doing what most other DLL based APIs do (Including the Win32 API), and have the function return the number of bytes of storage required (Or number of elements if you prefer) when passed a NULL pointer, and take a parameter to the function indicating the length of the buffer.

What is the exact error you get, and what line of code does it occur on? If it's when you access the vector (in almost any way), it's probably because of this problem.
Also, if you're static linking to the CRT (Default setting for VC6, optional in VC2003), you can't pass STL objects across a DLL boundary at all - you'll need to link to the DLL version of the CRT.
Thanks Evil ;
I use VC6 , as you say maybe error comes from static or dynamic linking. In those area I havent got enough information, can you send me a link or another think for learning this things. I dont want to ask everything, ok ?
I solved problem with another way. I have send a global structure(struct FILE_STRUCTURES * ) adress which is like that :

FILE_STRUCTURES FileStruct;


rv = ProcessFileDll( &localJP , &FileStruct );

structures are:

struct REC_STRUCTURE
{
char pan[10];
char panSq;
long chipPos;
int chipLen;
char chName[30];
};

struct FILE_STRUCTURE
{
int recCount;
int curretRecCount;
char filePath[256];
int jobId;
vector <struct REC_STRUCTURE> records;
};

struct FILE_STRUCTURES
{
int fileCount;
vector <struct FILE_STRUCTURE> fileStructures;
};

Now it is working , it gets what I want. It did not give an error about DLL boundry for sending STL objects.
Thanks for all ;)
Quote:Original post by Ahmet
Thanks Evil ;
I use VC6 , as you say maybe error comes from static or dynamic linking. In those area I havent got enough information, can you send me a link or another think for learning this things. I dont want to ask everything, ok ?
First, I'd advise upgrading your compiler. VC6 is not a C++ compiler, it's STL implementation is buggy, it has some fairly major bugs, is not supported any more, and is nearly 13 years old. VC 2008 Express is free to download and has none of these problems.

You want to go into the linker settings (Project settings -> Linker I think), and change "Run time library" from "Single threaded" to "Single-threaded DLL" (Or better, Multi-threaded DLL"). You'll need to do that for debug and release configs, in the DLL and the EXE.

Quote:Original post by Ahmet
I solved problem with another way. I have send a global structure(struct FILE_STRUCTURES * ) adress which is like that :

FILE_STRUCTURES FileStruct;


rv = ProcessFileDll( &localJP , &FileStruct );

structures are:

struct REC_STRUCTURE
{
char pan[10];
char panSq;
long chipPos;
int chipLen;
char chName[30];
};

struct FILE_STRUCTURE
{
int recCount;
int curretRecCount;
char filePath[256];
int jobId;
vector <struct REC_STRUCTURE> records;
};

struct FILE_STRUCTURES
{
int fileCount;
vector <struct FILE_STRUCTURE> fileStructures;
};

Now it is working , it gets what I want. It did not give an error about DLL boundry for sending STL objects.
Thanks for all ;)
That'll still have problems - you still have a STL object there. The problem comes from a push_back() or other method that causes a memory allocation happening in the DLL, and then the vector's destructor running in the EXE. With a static link to the CRT, you can't allocate memory in the DLL and free it in the EXE.

Quote: You want to go into the linker settings (Project settings -> Linker I think), and change "Run time library" from "Single threaded" to "Single-threaded DLL" (Or better, Multi-threaded DLL"). You'll need to do that for debug and release configs, in the DLL and the EXE.

Why did you gived me this information ? What will change when I do like that ?

Sory but my questions are not about game programming and I have to use VC6 because our company's projects, it is very huge (hundreds of code file). It is written on VC6 and converting project is very huge job. I cant do that actualy I have VC2008 EE now .
I want to understand one thing, is it not possible to use STL object like my way, you said that I cant allocate memory for stl object on dll function and deallocate its memory on exe, is it true ?
If it is true , is there any way to do like my job, I cant send plain memory objects like arrays because at this time I need hundred tens of MB memory for a single file which I have to analyze.


Quote:Original post by Ahmet

Quote: You want to go into the linker settings (Project settings -> Linker I think), and change "Run time library" from "Single threaded" to "Single-threaded DLL" (Or better, Multi-threaded DLL"). You'll need to do that for debug and release configs, in the DLL and the EXE.

Why did you gived me this information ? What will change when I do like that ?

Sory but my questions are not about game programming and I have to use VC6 because our company's projects, it is very huge (hundreds of code file). It is written on VC6 and converting project is very huge job. I cant do that actualy I have VC2008 EE now .
That will let you use a STL object across the DLL boundary, but only if the DLL and EXE use the exact same STL version. It changes the CRT to use the version in a DLL instead of embedding it into the EXE. This also has the advantage of making the EXE slightly smaller.

Quote:Original post by Ahmet
I want to understand one thing, is it not possible to use STL object like my way, you said that I cant allocate memory for stl object on dll function and deallocate its memory on exe, is it true ?
Correct. When static linking to the CRT, the EXE and DLL have totally different heaps. You cannot allocate memory from one heap and free it in another, and you cannot pass any CRT objects between EXE and DLL (E.g. FILE*).

Quote:Original post by Ahmet
If it is true , is there any way to do like my job, I cant send plain memory objects like arrays because at this time I need hundred tens of MB memory for a single file which I have to analyze.
There's two options:
1. Use the DLL version of the CRT - then both the EXE and DLL will load the CRT DLL, and use the same heap.
2. Do things the Win32 way, and give the function the ability to return the amount of memory it needs. The EXE then performs the following steps:
  • Call the function to get the buffer size required (Usually passing NULL as the buffer pointer)
  • Allocate the required buffer size
  • Call the function with the allocated buffer, passing in the size as well (So the function knows how large the array you passed it is)
  • Use the returned value
  • Free the memory.

    I'd still recommend the second method, since although it's more complicated, it's also a lot less of a problem if you ever switch compiler or STL version.
  • I have remembered the error , it's something like that :

    Invalid Address specified to RtlValidateHeap(#,#)

    I think it is about different heap memory as you said.

    Quote:
    You want to go into the linker settings (Project settings -> Linker I think), and change "Run time library" from "Single threaded" to "Single-threaded DLL" (Or better, Multi-threaded DLL"). You'll need to do that for debug and release configs, in the DLL and the EXE.


    I cant find something like that. My project is multi thread so every thread must have its own heap memory. So if I do my dll projects as Multi-threaded DLL , is the problem can be solved ?


    This topic is closed to new replies.

    Advertisement