Calling a native function from managed code - c++

I have a managed C++/CLI project which must use some native code. A simplified version of the native header file would be:
struct structA
{
// Some variables...
};
struct structB
{
// Some similar variables...
void convertTo(structA& dest);
};
This header is included in the managed code. The managed code has:
structA sA;
structB sB;
// Load data into sB...
sB.convertTo(sA);
I am using Visual Studio 2008 and compiling the managed code with /clr. This of course generates a linker error (LNK2028), as the implicit calling conventions differ. However I have been unable to use extern "C" declarations to solve this (or perhaps I'm using them wrong). I have tried several of the solutions provided to similar questions here, to no avail.
How do I correctly call the unmanaged function from the managed code? What declaration or wrapper is required here?

Turns out this was not a managed-unmanaged clash issue. I simply forgot to declare the used function as exported, i.e.,
__declspec(dllexport) void convertTo(structA& dest);
The second, more general linker error (LNK2019) for an unreferenced function was what I should have been paying attention to. It is strange that a managed-unmanaged clash error (LNK2028) was thrown as well, since this is a more specialized error (which also threw me off track). As far as I know, this error should only have applied was I to use /clr:pure, as was suggested in the comments as well.

Related

Not all functions were exported using dllexport

This question might be similar to
DLL Exports: not all my functions are exported
but as it was not fully answered there, I have to ask again. Also my case is because of the use of templates and exporting the whole classes slightly different.
Used environment: VS2008, cl9.0.
I have created a dll-project and added about 40 files (each class a file), mainly headers, because a lot of the classes are templates. An example of the heritage would be:
// Class1.h
template<class TYPE>
class TInt
{
// Some member functions here
// Also a function bool IsValid() const;
};
// Implementation of template here in the header
// Class2.h
#ifndef DllExpImpM
#define DllExpImpM __declspec(dllimport)
#endif
class DllExpImpM CInt : public TInt<double>
{
// Some member functions here
};
// Class2.cpp
// Some includes, including "stdafx.h", which sets DllExpImpM
// to __declspec(dllexport)
template class DllExpImpM TInt<double>;
// Implemenation of CInt
So far, it worked fine as long as I used the debug (compile) option. I was able the use the dll project from other projects.
But if the dll projekt is compiled as release (which works fine), I cannot use it from other projects, because the compiler complains that are some missing functions, e.g. that IsValid() in TInt. I used the dependency walker to check it, and indeed, the compiler is right! The member function IsValid() was not exported, along with another function and with a constructor und the destructor. All other member functions of TInt are exported, I can see them using the dependency walker, I can use them from other projects. This also happens in a similar way with one other class.
I then compared the debug dll and the release dll using the dependency walker and winmerge. They are almost identical, just that the release dll is missing a few functions (about 3 %).
I have no idea what is wrong. I know that I do not have a lot information (the whole information is much too big and I yet could not find a simple example that does not work) and to me all sounds a little bit weird. But perhaps anyone out there once had the same problem. I appreciate every idea very much.
Thank you!
If it works for debug, but not release, then you need to identify what is different. My first guess would be that a #define macro or an equivalent /D macro us not getting defined or is getting defined wrongly.
Maybe DllExpImpM or maybe something else.
If not a macro, then what else changes between builds?
Here are some things I found when I ran into this.
I had the same issue, but taking off the /GL parameter didn't make any difference.
My first test was creating a very simple funcion - void test () - and trying to export it. That didn't work until I got rid of the whole output directory (x64 in my case) and rebuilt it all. It would guess that some intermediate file was messing my compilation, anyway, I didn't investigate it further.
But there was still one function that wouldn't be exported. I took some time to realize the declaration in the .h file wasn't matching exatly the signature in the .cpp file! I was missing a parameter in the .h file... I don't know why it was even compiling, anyway, fixing that allowed the function to be exported.

How to best avoid double thunking in C++/CLI native types

Tradionally, I've been using MFC extension dll's and importing/exporting using dllimport/dllexport.
However, when the dll is changed to use /clr, this method becomes costly as calls can result in a double-thunk. I'm taking a massive performance hit at the moment and need to stop the double-thunks. The solution I've seen described suggests making sure everything is using __clrcall convention, but this does not work with dllexport.
Microsoft's own section on double-thunking suggests:
Similarly, if you export (dllexport, dllimport) a managed function, a native entry point is generated and any function that imports and calls that function will call through the native entry point. To avoid double thunking in this situation, do not use native export/import semantics; simply reference the metadata via #using (see #using Directive (C++)).
To me, this reads as though I can remove dllexport/dllimport from my classes and stick a #using in my stdafx.h. For native types, however, this results in LNK2028 (unresolved token) and LNK2019 (unresolved external symbol). It makes no difference whether I include the .lib in the linker or not; I still get this error.
So, my question is how best to avoid double-thunking and import native types from a C++/CLI library?
Regards
Nick
** UPDATE **
Some updates from testing.
As soon as the dll is compiled with /clr, double thunking occurs for native types (using dllexport/dllimport).
This can be mitigated by turning CLR support off on a file by file basis. This is a pain, and sometimes native types use the clr so this can't be done everywhere. And the callee must be compiled native too for it to work.
Methods can be marked __clrcall but this will result in a compilation error when mixed with dllexport. However, I have managed to make the following code work without a double-thunk:
// MFCCLRLIB_API is defined in the library only (as dllexport)
// but NOT defined when using (dllimport)
// MFCCLRLIB_CALL is defined as empty in the library,
// but __clrcall when using.
#ifndef _MFCCLRLIB
#define MFCCLRLIB_API
#define MFCCLRLIB_CALL __clrcall
#endif
class MFCCLRLIB_API ThunkHack
{
public:
ThunkHack();
ThunkHack(const ThunkHack&);
~ThunkHack();
};
class MFCCLRLIB_API ThunkHackCaller
{
public:
ThunkHackCaller(void);
~ThunkHackCaller(void);
virtual void MFCCLRLIB_CALL UseThunkClass(ThunkHack thunk);
};
This compiles and I can use the caller class now from outside the library and it doesn't result in a double thunk. Which is what I want. I'm concerned, however, that this is not the way to do it; I haven't read anything that suggests this approach is safe.
I'd really like some guidelines on how to used mixed-mode C++ libraries effeciently to avoid performance hits of the like we are seeing.
-Nick

In C++, how to use a singleton from a separate source file?

I'm trying to compile some other people's wrapper program on a large system, in which it's using a global object from another file, the definition of the class is like:
class __declspec(dllexport) A
{
...
static A * instance;
}
And in my separate source file (which I want to build to a .exe), I included the header file A.h, and declare at the beginning like this
A * A::instance;
to access the data in A.
The problem is, this piece of code can be built successfully on Linux, now when I try to build it in windows NT, it will have issues.
If I leave it like this, the compiler will complain with a C2491 error, definition of dllimport function not allowed.
If I remove this line of A declaration, I'll get a lot of error LNK2001: unresolved external symbol.
Not quite sure what is the problem here, I did some research online, but couldn't find a good answer, I myself is not that familiar with dll import/export and some C++ tricks either. Can some one provide some insights on the problem or which direction should I spend my time on to figure this out?
Or say, if I already have a static object like this, and I want to write another program to access it, how exactly should I do?
Please also correct me if I made any mistakes here. Thanks!
I think the keyword you need is extern, as in:
extern A *A::instance;
This says the variable A::instance is defined somewhere else, but you're telling the compiler about it so you can use it by name in this file.
__declspec(dllexport) is used when you want to export your function in a DLL. It should not be necessary as long as you're not calling the class from another DLL.
But I suspect your problem is related to using .c files and not the class specification. Try to read this by the way. It discusses dllexport in just-enough-detail Windows & C++: extern & __declspec(dllimport)
Singleton usually has a function, like
A::instance = NULL;
A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
If you have a function like this you don't have to access A::instance directly.
And sorry, but what are you doing? Including a C++ header in a C program? Does it even compiles?
Personally I usually hide the instance in the .cpp file in an anonymous namespace. Then I provide a getInstance() function that returns a pointer or reference to it and I dllExport that function.
If you want to enforce things you can make the constructors for A private and make getInstance a friend.

VS2008 to VS 2010 migration - a breaking change?

I encountered a problem when migrating our C++ code from VS2008 to VS2010. I can't find an explanation for the reason of it so far and will appreciate your help.
We have a custom memory allocator and it resides in a dll. In the rest of the code we use the preprocessor to redirect the allocations to our functions. Thie following simple code compiles correctly in VS2008, but does not in VS2010.
in stdafh.h:
#define free my_free
#include <string>
In VS2010 I get:
1>d:\program files\microsoft visual studio 10.0\vc\include\xdebug(62): error C3861: 'free': identifier not found
Coming from the line:
template<class _Ty>
void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
{ // delete from the debug CRT heap even if operator delete exists
if (_Ptr != 0)
{ // worth deleting
_Ptr->~_Ty();
// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
// facets allocated by normal new.
free(_Ptr);
Any help or ideas will be highly appreciated!
Moshe
According to the C++ ISO standard, section 17.4.3.1.1.2:
A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
This means that it's not legal to #define a library function name to mean something else. I guess this just happened to work in VS2008, but when migrating to VS2010 the compiler authors came up with an implementation in which this does not work properly.
If you want to redefine what free does, I suggest doing it through a more conventional channel by linking the code against your own implementation of the C library that changes the default behavior.
After some investigation using the /P option to create the preprocessor files and studying them I've found the root cause of the issue.
The xdebug header, which describes itself as "debug heap support header for Microsoft", contains the following lines:
#pragma push_macro("free")
#undef free
which obviously defeat our attempts to redefine it. So this is not something new to the compiler, just plain #undef that happens to occur with the functions we try to redefine

Strange linkage problem with Visual C++ 2005

please help me, I have a strange problem which i can't sort out in any way.
Premise: I'm using visual c++ 2005 on windows 7 x64, and I'm sure that my code isn't fatally flawed because with g++ under Linux it runs nicely.
I am developing an application which uses a static library also developed by me.
In the link phase of the application i get two mysterious LNK2019 errors.
This is the header of one of the classes of the library:
namespace sulfur
{
class Quark
{
public:
... various methods
void addAccel(const Vec2 &a);
... various methods
private:
... various data
};
}
Obviously in the cpp file i provide an implementation for addAccel with exactly the same signature.
When I try to link the application with the library, ALL the other member functions are found, except for addAccel.
The linker searches for the symbol "?addAccel#Quark##QAEXABV?$TemplateVec2#M#Atlax###Z"
while in the .lib file there is (which i found using dumpbin) "?addAccel#Quark#sulfur##QAEXABV?$TemplateVec2#M#Atlax###Z". The only difference here is that the linker searches for a mangled name without the namespace part and I don't know why.
I've tried to change name, position, calling convention and signature of the metod but to no avail, always getting the same error.
The second error is very similar. I have another header in the library:
namespace sulfur
{
class Cluster
{
...
Quark *addQuark(sulfur::Feature feat, float x, float y, float m=0.1f, float aF=0.01f);
...
};
}
and a correct implementation file is provided. Like before, all the other methods are linked properly, but not addQuark.
The linker searches for "?addQuark#Cluster#sulfur##QAEPAVQuark##W4Feature#2#MMMM#Z"
but in the library there is "?addQuark#Cluster#sulfur##QAEPAVQuark#2#W4Feature#2#MMMM#Z".
This time the difference is the absence of the first '2' between the '#' in the version which the compiler searches for.
This isn't the first time that I build this application with visual studio and it has always linked ok except for this time with the last changes.
I don't have any clue,
thank you in advance
Where and how is the void addAccel(const Vec2 &a); function implemented? Are you sure that you are not missing Quark:: prefix on the implementation of the function?
Well, I've just solved the issue.
There where two erroneous forward declarations (outside of the namespace) of class Quark and class Cluster. For some reason g++ was ok with that, while VC++ was right to complain about it.
Thank you anyway.