export typedefs in .NET dlls - c++-cli

I've written a wrapper for a C++ dll in C++/CLI. Inside the wrapper, I made some typedefs. Is there a way to export these names as .NET classes?
Background: the typedef'd classes are some templates. For these templates to work, you need a managed and a native parameter (this is part of the translation). This is impossible for the client of the wrapper to program / know. That's why he needs the different aliases for the used versions of the template.

I exchanged the typedefs with some new class definitions that derive from the template. This should work.

I do not have too much information but typedefing should work only on Clr types. Generic classes, maybe but template classes can not ne typedefed. Also among native types, only the ones that are common (the word "common" may not be correct here.) to .net i.e. double, int, char, Char* (not char*) etc.
This code works and introduces a "new" type to clr.
namespace example
{
#ifdef _WIN64
typedef sizeT UInt64
#else
typedef sizeT UInt32
#endif
}
Now you have size_t of .Net, whose size depends on platform.

Related

What's the corresponding C++ native type of C++/CLI System::String^

I need to rewrite a C++/CLI project to native C++ project, by removing or replacing managed codes. I'm not very familiar with C++/CLI,so, what's the corresponding C++ native type of C++/CLI System::String^, is it std::string or std::string*?
For example a C++/CLI function Foo(System::String^ location), rewrite it to Foo(std::string location),is this right?
It's probably std::string though it depends on your ownership intentions. For example, the closest translation of String^ (ignoring the shared memory part for the moment) would be a std::string& which is known as a reference - effectively a pointer except they are never null and cannot be manually de-allocated. A class is more likely to have std::string members (meaning that it owns that data) than std::string& members (meaning it does not own that data)
The other question for function signatures is whether Foo is allowed to mutate the location object. If it isn't, a const std::string& parameter should be used
It's probably not std::string* as 'raw pointers' are quite rare to use in modern C++. You generally create objects on the stack and pass them around using references, allowing RAII to manage the memory - I would definitely read up more on RAII which explains the ownership model and is very important for writing C++

What .NET type marshalls to COM UINT?

In C# I am declaring an interface, which will be exposed to COM for use by C++. Our spec says one integer parameter should be [in]UINT uiVal. I'm using int in C# and it is being exposed as long.
It's not a big deal, but how can I force it to marshall to UINT rather than long? Some specific .Net type, or do I need to add attributes to the C# parameter somehow?
UINT is a type alias from the Windows SDK, you will never get it out of a type library. Tooling that translates type libraries, like the #import directive you are using, pick native C types. History plays a role, COM was originally designed for the 16-bit version of Windows. When long was important to declare a 32-bit integer.
Closest you can get is uint in the C# declaration, it will be translated to unsigned long in your C++ code. Which is fine, it is still a 32-bit type, Microsoft chose the LLP64 data model for 64-bit code. They did not have much of a choice. Unlike the LP64 model chosen in *nix. They did not have much of a choice either, the Y2K38 disaster is approaching fast :)

Can I use native primitive types in C++/CLI?

The same as C#, int is an alias for System::Int32, which is an CLR type. Is there a way I can use a native "int", which means int in standard c++?
C++/CLI primitive types have dual identity. The type keywords match both the native C++ type and the CLR type, depending on context. And variables with native type sort of inherit the methods available on the CLR type, like ToString.
I think this blog article explaining the relationship between native and managed types is pretty helpful: http://blogs.msdn.com/b/branbray/archive/2005/07/20/441099.aspx
I think the accepted answer does not answer the OP's question.
If the /clr compiler switch is on, then the int keyword means System::Int32, it is not native.
If the /clr compiler switch is off, then the int keyword means native C/C++ int, it is not managed.
Using System::Int32 implies a significant performance penalty over native int (you can measure it).
You can turn off the /clr compiler switch per .cpp file. It is not a Project option, it is a translation unit (.cpp file) option.
Right click on the file, then properties, etc...
So, you can write some native code in a .cpp file (compiled with /clr off).
Then you can write managed code in another file (compiled with /clr on) and invoke the native code.
They're the same thing, go ahead and use int everywhere you want the native type.

Mixed management in C++

I have added a class to my program and tested it. I was really surprised that there was any real errors. Here is the code:
#pragma once
#include "Iingredient.h"
#include <string>
#include <vector>
using namespace std;
ref class Recipe{
private:
string partsName;
vector<Iingredient> ing;
public:
Recipe(){}
};
And here are the errors:
Error 23 error C4368: cannot define 'partsName' as a member of managed
'Recipe': mixed types are not
supported c:\users\user\documents\visual studio
2010\projects\smestras2_l1\Recipe.h 10 1 file2_L1
Error 24 error C4368: cannot define 'ing' as a member of managed
'Recipe': mixed types are not
supported c:\users\user\documents\visual studio
2010\projects\smestras2_l1\Recipe.h 11 1 file2_L1
I googled a bit and found out that its about managed and unmanaged code.
How to fix this? Is it related with manged and unmanaged code or not? if so how?
I agree with others: you shouldn't use C++/CLI in most circumstances, you should use C# (or another "normal" managed language) for that (assuming you want to write a .Net application). C++/CLI is useful mostly in special circumstances, like interoperating between managed and unmanaged code.
If you're sure you want use C++/CLI, you can't put native classes into managed ones. But you can put pointers to native classes there:
ref class Recipe{
private:
string* partsName;
vector<Iingredient>* ing;
};
The code above works. But you have to keep in mind that those are normal native C++ pointers and that means you have to manually delete them. To do that property, you should read about how destructors and finalizers work in C++/CLI.
When defining ref class Recipe, you made it managed. But std::string and std::vector are umanaged types. You are trying to declare native variables in managed class, but it is not allowed.
Seems, you are novice in C++. Just, don't use C++/CLI. Consider C#, if you target .Net or unmanaged C++.
You cannot use unmanaged types in a managed class, ref keyword, because the heap and the managed heap are two different types of memory. To solve this specific problem you can use a managed string type (System::String^). The carrot tells the compiler that the type is a handle to a managed class.
Another way of going about this problem is to use pointers, that way the pointer will be on the managed heap, and the actual memory for that object will be in the standard unmanaged heap, which is where Recipe is located.
To construct your Recipe class you would have to do
Recipe^ recipe = gcnew Recipe();
With no idea of c++-cli, I can try and guess that the problem is that you are defining a reference type and trying to use C++ types inside (a std::string field) rather than whatever the equivalent managed type is (String?).
The reason why this can be problematic is that it mixes resource management approaches. Reference types are intended to be used out of a garbage collector, and unless you implement a destructor or IDisposable will just be ignored once proven that the last reference is lost. On the other hand, to be able to manage the memory in the internal field the std::string destructor must be called.

Is there anything in the C++0x standard to support separate compilation of templates?

In current g++, I typically include all my templated functions that take the template parameter as an argument because they have to be compiled for each instance.
template<typename T>
class A {
public:
void f() { ... }
};
So in a different source, I would write:
#include <A.hh>
A<int> a1;
a1.f();
A<double> a2;
a2.f();
Sometimes, when I've been desperate to not inline big methods, I've manually specified which classes will be used in the source file, but it's really obnoxious:
template<typename T>
A::A() { ... }
template<typename T>
void A::f() { ... }
A<int>; // manually trigger code generation for int and double
A<double>;
Obviously different IDEs and compilers have mechanisms to support this. Is there anything standard that has been mandated, and/or does g++ support anything like this?
There's nothing in the proposed C++0x standard. In fact, export template has been removed (few compilers implemented it anyway).
As far as inlining is concerned, it's a total non-issue. The compiler is smart enough not to inline functions which are too big, even if they're marked inline and put into a header file.
If you're looking at increased compile times from header files grown bloated from templates, use precompiled headers. These aren't standard, but almost all current compilers provide such a mechanism.
C++0x does have extern template, which allows you to prevent the instantiation of certain templates in a compilation unit. So if you have a template class SomeClass, you can put this in the header:
extern template SomeClass<int>;
extern template SomeClass<double>;
This will prevent users from instantiating the template. In the .cpp file for the template, you can force instantiation with this syntax:
template SomeClass<int>;
template SomeClass<double>;
I've manually specified which classes will be used in the source file, but it's really obnoxious:
A<int>; // manually trigger code generation for int and double
A<double>;
This is not legal (I assume you meant to declare dummy variables here, and missed their name). We will see below why
Is there anything standard that has been mandated, and/or does g++ support anything like this?
C++03 had something called export, but which turned out to be a misfeature. The EDG implemented that feature, and their experience with it indicated that it's not worth the trouble implementing it. And it doesn't provide a useful feature separate compilation usually gives you: Hiding of the code of templates which you once compiled. export still requires the code of templates, be it in raw form or encoded into a mid-level compiler-specific language. See Why we can't afford export. A short example is given by EDG worker David Vandevoorde here.
For C++0x and for C++0x sans export, we have
A function template, member function of a class template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated (14.7.1) unless the corresponding specialization is explicitly instantiated (14.7.2) in some translation unit; no diagnostic is required
As this indicates, the only way you can achieve separate compilation is to explicitly instantiate the template you want to have separately compiled. By defining dummy variables, you merely implicitly instantiate the class template. And you do not instantiate the member functions of the class templates that way - you would need to do dummy calls or take their address. And to all this, you are not guaranteed that an implicitly instantiated function won't be discarded if it's not used in the translation unit it was instantiated by, after optimization, based on the above quote.
So you explicitly instantiate the class template, which will explicitly also instantiate its member functions the following way:
template class A<int>;
template class A<double>;
This feature, called export is present even in the current standard of C++. Unfortunately, most compilers, including gcc, do not support it. See here http://gcc.gnu.org/bugs/