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

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++

Related

C++/CLI: are local managed variables allowed in unmanaged class methods?

I know gcroot is used for holding a refrence to a managed object in a native class, but what about using managed objects as local variables inside an unmanaged class function ?
The compiler does not seem to generate an error on this, but is it "proper" ? Does it hurt performence?
There is no such thing as a local managed object. All managed objects are stored on the heap, required to let the garbage collector do its job. You could only have a reference as a local variable. A pointer at runtime.
Using an managed object reference in an unmanaged function is possible if you compile that code with /clr or #pragma managed in effect. Such code will be translated to IL and gets just-in-time compiled at runtime, just like normal managed code. It won't otherwise have the characteristics of managed code, there is no verification and you'll suffer all the normal pointer bugs. And yes, it can hurt performance because such code doesn't get the normal optimizer love. The optimizer built in the jitter isn't as effective because it works under time constraints.
Compile native code without the /clr option or use #pragma unmanaged inside your code to switch the compiler on-the-fly.
Managed objects, both values of managed value types (value struct, value class, enum class) and handles to managed reference types (ref struct, ref class) can be used inside code which is compiled to MSIL.
And code that is compiled to MSIL can be part of unmanaged objects (for example, a virtual member function of a standard C++ type can be compiled to MSIL, and the Visual C++ compiler "It Just Works" technology will make sure that the v-table is set up correctly). This is extremely useful when forwarding events and callbacks produced by standard C++ code into the managed GUI world. But it is also applicable if you have an algorithm implemented in managed code (perhaps C#) that you want to call from C++.
As Hans mentions, there are performance implications of switching between MSIL and machine code generation for a particular function. But if you are sitting on a native-managed boundary, then compilation to MSIL and use of the "It Just Works" a/k/a "C++ interop" is by far the highest performance alternative.

Is there a conventional URI scheme for referencing code in a library?

Is there a standard or conventional URI scheme, like file: or http: for referencing objects in a dynamic library?
For example, if I were to represent a function in a library in the form of a unique string that can be used to look up that function (by whatever reflective means), how might I do that?
Specifically I'm developing this in Objective-C, and I assume different languages/platforms will have different representations (I know .NET has its own), but I'm curious about this in a more general sense.
No, the name of the symbol is derived from its name in your code. In windows you will assuming C or C++
HMODULE module=LoadLibrary( [path to your dll] );
//If the exported name is foo.
Function foo=(Function)GetProcAddress(module,"foo");
//Call function
foo();
FreeLibrary(module);
The exported name is compiler-dependent.
Acually such a naming scheme is quite useless. In C++ you can use something like (Note that you will have one FunctionCaller per function prototype)
FunctionCaller("your-dll.dll/foo")();
Where the constructor of FunctionCaller loads the library, calls foo and frees the library. However it is not good because:
it may happen that the return value points to a resource inside the library and then will become useless
loading libraries and perform function look-up is slow relative to calling the function found
What you do is
Load the library
Load functions that you will need
Use your functions
Free the library
Here you would need to refer to more than one symbol at a time which would require a more complex scheme than uri.
EDIT: If you want to the convenience of calling functions like that you could have a surviving FunctionCaller object that keeps all loaded modules and contains a map from function name to address for each loaded library.

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 WCHAR in COM interfaces a good thing?

Is WCHAR in COM interfaces a good thing ?
I've been searching the internet for an answer to this question with no results.
Basically should char* / wchar* be used in COM or should i use BSTR instead ?
Is it safe or does it depend ?
In this code example its strings (code grabbed from a random source):
STDMETHOD(SetAudioLanguageOrder(WCHAR *nValue)) = 0;
STDMETHOD_(WCHAR *, GetAudioLanguageOrder()) = 0;
I'm confused over when to use what with all marshaling, memory boundaries, etc. that comes up when talking about COM.
What about data buffers (byte*) ?
It depends on the context in which the caller will call you. First, if you use a non-automation type, marshaling will not be automatically performed for you. Therefore, you'll end up having to write your own marshaler to move a wchar_t* across process boundaries.
That said, there's no rule that says you can't pass a wchar_t* in a COM interface. There are many COM interfaces that pass custom types (structs, pointers to structs, callbacks, etc), and it's all just about your needs.
In your interface, if you do use WCHAR strings, I'd declare SetAudioLanguageOrder this way:
STDMETHOD(SetAudioLanguageOrder(const WCHAR *nValue)) = 0;
This makes it clearer who is (not) supposed to free the string, and provides more context as how to treat the string (the caller is discouraged from modifying the string, though the caller can certainly force that behavior if they want to write bad code).
The GetAudioLanguageOrder call is OK, but now the question is: who frees the returned string, and how should it be freed? Via free(...)? Or C++ delete[]? If you use a BSTR, then you know - use SysFreeString. That's part of the reason to use BSTR's instead of WCHAR strings.
If you are going to support dual interfaces and clients other than C++, use BSTR. If all callers are C++, then WCHAR* is fine.
You will have to be able to know the length of that array in one way or another. In C or C++ it's typical to use null-terminated strings and you often use them within one process - the callee accesses the very same data as the caller prepared and null-terminated.
Not the same with COM - you might want to create an out-proc server or use your in-proc server in a surrogate process and then you'll need marshalling - a middleware mechanism that transmits that data between processes or threads - to work. That mechanism will not know about the size of the string unless you one of MIDL attributes such as size_is to specify the right array size. Using those attributes will require an extra parameter for each array - that complicates the interface and requires extra care while dealing with data.
That said, in most cases you get a more fluent interface by just using BSTRs.

Converting c++ project to clr safe project

I need to work on converting a very huge c++ project to clr safe. The current c++ project has a lot of stuff from c++ like templates, generics, pointers, storage/stream, ole apis, zlib compression apis, inlines etc. Where can I find the datiled document for this type of conversion? Can you suggest some good book to refer to? If anyone of you have done such conversion, can I get some analysis from you?
I'll just cough up the MSDN Library article titled "How to: Migrate to /clr:safe
Visual C++ can generate verifiable components with using /clr:safe, which causes the compiler to generate errors for each non-verifiable code construct.
The following issues generate verifiability errors:
Native types. Even if it isn't used, the declaration of native classes, structures, pointers, or arrays will prevent compilation.
Global variables
Function calls into any unmanaged library, including common language runtime function calls
A verifiable function cannot contain a static_cast Operator for down-casting. The static_cast operator can be used for casting between primitive types, but for down-casting, safe_cast or a C-Style cast (which is implemented as a safe_cast) must be used.
A verifiable function cannot contain a reinterpret_cast operator (or any C-style cast equivalent).
A verifiable function cannot perform arithmetic on an interior_ptr. It may only assign to it and dereference it.
A verifiable function can only throw or catch pointers to reference types, so value types must be boxed before throwing.
A verifiable function can only call verifiable functions (such that calls to the common language runtime are not allowed, include AtEntry/AtExit, and so global constructors are disallowed).
A verifiable class cannot use Explicit.
If building an EXE, a main function cannot declare any parameters, so GetCommandLineArgs must be used to retrieve command-line arguments.
Making a non-virtual call to a virtual function.
Also, the following keywords cannot be used in verifiable code:
unmanaged and pack pragmas
naked and align __declspec modifiers
__asm
__based
__try and __except
I reckon that will keep you busy for a while. There is no magic wand to wave to turn native C++ into verifiable code. Are you sure this is worth the investment?
The vast majority of native C++ is entirely valid C++/CLI, including templates, inlines, etc, except the CLR STL is rather slow compared to the BCL. Also, native C++ doesn't have generics, only templates.
The reality of compiling as C++/CLI is to check the switch and push compile, and wait for it to throw errors.
Rewriting native C++ into safe C++/CLI will result in a code that is syntactically different, but semantically same as C#. If that is the case, why not rewrite directly in C#?
If you want to avoid what is essentially a complete rewrite, consider the following alternatives:
P/Invoke. Unfortunately, I'm unfamiliar whether this would isolate safe from unsafe code. Even if it can perform the isolation, you'll need to wrap your existing C++ code into procedural, C-like API, so it can be consumed by P/Invoke. On a plus side, unless your API is excessively chatty, you get to keep (most of) your native performance.
Wrapping your C++ into out-of-process COM server and using COM Interop to consume it from the manged code. This way, your managed code is completely protected from any corruption that might happen at C++ end and can remain "safe". The downside is a performance hit that you'll get for out-of-process marshaling and the implementation effort you'll need to expend to correctly implement the COM.