Sign in to follow this  

Sending a structure which has vector to dll function as parameter

This topic is 2482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 ?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ;)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.


Share this post


Link to post
Share on other sites
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.

    Share this post


    Link to post
    Share on other sites
    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 ?


    Share this post


    Link to post
    Share on other sites
    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.


    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 ?
    I don't recall where exactly it is (It's been ~5 years since I last used VC6), in VC2008 it's in Project settings (Alt+F7) -> C/C++ -> Code Generation -> Runtime Library (Not in linker, sorry). For your debug build you'll want "Multi-threaded Debug DLL", and for the release build you'll want "Multi-threaded DLL".
    Doing that should solve the problem, but still means you need to use the exact same STL version (Which as I said, could be a problem later on).

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Ahmet
    Thanks for all, I did it. But I think you mean CRT version...
    No - you'll still need to use the same STL version. If you have a STL object (E.g. std::vector) used by the EXE and the DLL, then you can't compile the EXE with VC6 and the DLL with VC2003, or any other compiler or STL version.

    Share this post


    Link to post
    Share on other sites
    The Standard Template Library consists of header only (at least I don't know any exception). This means that everything from the STL you use will be compiled into your executable (remember, templates are compiled when instantiated, not when defined) or DLL. If the implementation of the STL changes and you use that new version in a single executable / dll, then you will have to recompile everything else as well.

    THe CRT can be switched, I think...

    Share this post


    Link to post
    Share on other sites
    I am facing similar issue. I am using Visual Studio 2008. I am not facing this issue of std::vector accross the dll in debug mode but in release mode only.
    Can one please help me help me out?

    Function returns "const std::vector<boost::intrusive_ptr<node> >"

    Share this post


    Link to post
    Share on other sites

    This topic is 2482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

    If you intended to correct an error in the post then please contact us.

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

    Sign in to follow this