I am writing a XLL (using XLW library) that calls a DLL function. This DLL function will get a vector reference, modify the vector and return it by argument.
I have a VS10 solution with several c++ projects, some DLLs and a XLL that will call DLL functions from excel. I compiled everything using VS10 compiler, with _HAS_ITERATOR_DEBUGGING=0
and _CRT_SECURE_NO_WARNINGS
and used same runtime library (/MDd) for all projects.
I also had to rebuild the XLW library to comply with _HAS_ITERATOR_DEBUGGING=0
that I have to use in my projects.
When calling the xll_function I was getting Heap Corruption errors and couldn't figure out why. After I tried resizing my vector before calling the dll function the error was gonne. That is, I can call the function and get the right vector returned by argument and no heap corruptions.
Could someone shed some light on this? As I am new to using DLLs I'm not sure if this should happen or if I am doing something wrong.
As you can see in the code below, the dll function will try to resize forwards
and that is the point that I think is generating the heap errors.
I'm trying to understand why this happens and how this resizing and allocation works for dlls. Maybe I can't resize a vector allocated in another heap.
** Code below - the first function is a static method in a class from a dll project and the second function is exported to the XLL.
void dll_function(double quote, const std::vector<double>& drift, const std::vector<double>& divs, std::vector<double>& forwards)
{
size_t size = drift.size();
forwards.resize(size);
for( size_t t = 0; t < size; t++)
{
forwards[t] = (quote - divs[t]) * drift[t];
}
}
MyArray xll_function(double quote, const MyArray& drift, const MyArray& divs)
{
// Resizing the vector before passing to function
std::vector<double> forwards(drift.size());
dll_function(quote, drift, divs, forwards);
return forwards;
}
To pass references to std::vector or other C++ collections across DLL boundaries, you need to do following.
Use same C++ compiler for both modules, and same version of the compiler.
In project settings, set up same value to the setting General / Platform Toolset.
In project settings, set up C/C++ / Code Generation / Runtime Library value to “Multi-threaded DLL (/MD)”, or Multi-threaded Debug DLL (/MDd) for debug config. If one of the projects have a dependency which requires static CRT setting, sorry you’re out of luck, it won’t work.
Use same configuration in both sides: if you’ve built debug version of the DLL, don’t link with release version of the consuming EXE. Also don’t change preprocessor defines like _ITERATOR_DEBUG_LEVEL or _SCL_SECURE_NO_WARNINGS, or if you did, change them to the same value for both projects.
The reason for these complications, C++ doesn’t have standardized ABI. The memory layout of std::vector and other classes changes based on many things. Operators new
and delete
are also in C++ standard library, i.e. you can’t allocate memory with C++ in one module, free in different one.
If you can’t satisfy these conditions, there’re several workarounds, here’s a nice summary: https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL