I'm trying to write a managed wrapper (C++/CLI) around an unmanaged C++ static library and am having two problems:
The unmanaged library uses std::shared_ptr in its headers. <memory> is included, and the header compiles as part of an unmanaged project. When I include this header in the managed project, however, I receive this error:
error C2039: 'shared_ptr' : is not a member of 'std'
How do I access the Values collection of a SortedDictionary<K, V> from C++/CLI? I cannot seem to find any examples of the proper syntax, and the C#-style syntax does not compile.
Code for #1:
// 1>Dummy.h(10): error C2039: 'shared_ptr' : is not a member of 'std'
#pragma once
#pragma managed(push, off)
#include <memory>
class Foo {};
typedef std::shared_ptr<Foo> FooPtr;
#pragma managed(pop)
using namespace System;
namespace Dummy {
public ref class Class1
{
public:
Class1(FooPtr);
};
}
shared_ptr lives in <memory> not <functional>. Make it look similar to this:
#pragma managed(push, off)
#include <memory>
#include "yourUnmanagedLibrary.h"
#pragma managed(pop)
Second question (ask only one please):
using namespace System::Collections::Generic;
...
SortedDictionary<int, String^>^ coll = gcnew SortedDictionary<int, String^>;
coll->Add(1, "one");
coll->Add(0, "zero");
for each (String^ value in coll->Values) {
Console::WriteLine(value);
}
I have found the answer here: Edit $(IncludePath) "macro" in Visual Studio 2010
Visual Studio 2010 is including the headers from Visual Studio 2008, which do not have shared_ptr.
The exact resolution is described here. The Platform Toolset on the General tab defaulted to vs90. Changing this to vs100 resolved the issue.
Related
The code bellow compiles without a warning on GCC and issues an error with clang (any c++11 compatible versions of both clang and GCC).
Which compiler is right with respect to the standard?
Specifically, is it allowed to declare as friend a non partially specialized template alias which is a partial template specialization of a class?
This makes me think that it might not be allowed:
cppreference says: "Friend declarations cannot refer to partial specializations [...]".
And also: "A type alias declaration introduces a name which can be used as a synonym for the type denoted by type-id. It does not introduce a new type [...]".
Finally: "Both function template and class template declarations may appear with the friend specifier [...]". It implicitly excludes the possibility for a template alias to be a friend of a class as an actual template alias but rather as the aliased class template, which is a partial specialization in the snippet bellow.
However, this makes me think that it might be allowed:
cppreference says : "An alias template is a template [...]". I undestand that a template alias is a distinct template. By consequence, declaring it as friend as in the following example without partial specilization of the class template alias is valid... Or not.
This code (not from me) also gives a workaround and let me think that there is no obvious reason for making the following code ill-formed.
This post asks a very similar question but no clear answer was provided with respect to the specific usage of an intermediate template alias.
template<typename T,typename N> class B{};
template<typename T> class A{
// template<typename U> friend class B<T,U>; fails as expected
template<typename N> using alias = B<T,N>;
template<typename N> friend class alias;
};
Intent: legal way to declare a partial specialization as friend using an intermediate alias (workaround).
Result: GCC is happy with it and produces the intended behaviour. Clang produces the following error:
<source>:7:35: error: redefinition of 'alias' as different kind of symbol
template<typename N> friend class alias;
^
<source>:6:22: note: previous definition is here
template<typename N> using alias = B<T,N>;
I am confusion.
I'm learning about the ofstream, it seems that it's really a basic_ofstream according to:
https://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream
https://msdn.microsoft.com/en-us/library/7z434859.aspx
What is the reason for a class named basic_ofstream with a constructor named ofstream? 'basic' implies that there is a non-basic version. Why is the constructor name different than the class name?
There is no constructor named ofstream (constructors don't have names), and there's no class named basic_ofstream (despite of what Microsoft documentation claims).
basic_ofstream is a class template (which is different from a class), and ofstream is a typedef name a.k.a. type alias that refers to one instantiation of that template, specifically to basic_ofstream<char>.
wofstream is another such name that refers to basic_ofstream<wchar_t>.
This is the naming convention that the C++ standard library uses to define different variants of types that differ in the character type they use. Another set of names that follows this convention is basic_string, string and wstring.
This is not constructor named differently. It's a specialization. So basic_ofstream is a template. Then you have two "shortcut names":
ofstream for basic_ofstream<char>
wofstream for basic_ofstream<wchar_t>
Why are they named basic... maybe because standard library provides only basic versions and client can write non-basic classes and plug them in. If you look at c++ standard io library diagram, all components are prefixed as "basic".
It's usually by replacing basic_streambuf any tying custom streambuf to stream. One example taken from boost
#include <ostream>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
int main()
{
io::stream_buffer<io::file_sink> buf("log.txt");
std::ostream out(&buf);
// out writes to log.txt
}
It's a buffer implementation working with std::ostream.
If you want to explore fancy implementations you can checkout more from boost::iostreams library and their examples. Nice one is with gzip. It works with ifstream:
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
int main()
{
using namespace std;
ifstream file("hello.gz", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(gzip_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);
}
I'm using C++/CLI only to unit test unmanaged C++ code in VS2010. I switched the compiler to /clr and using the unmanaged code from a static library.
I have a simple int property in my test class.
I would like to pass that as a const int & to a function in native C++. But it can't compile and I've found out that, it's because you can't mix references like that.
What is the way to do it, I tried to following and it's working, but is there a nicer way?
[TestClass]
public ref class MyTestClass
{
private:
int _my_property;
public:
[TestMethod]
void MyTestMethod()
{
MyNativeClass c;
// c.SomeMethod(_my_property) this doesn't work
int i = _my__property;
c.SomeMethod(i) // this works
}
}
C++ references are really just syntactic sugare for pointers. A C++ pointer points to a specific point in memory, while CLI references can be freely moved around by the garbage collector. To pass a reference to an object in managed memory to unmanged code, you need to pin the pointer.
More info and sample in another SO question: Convert from C++/CLI pointer to native C++ pointer
Edit 2
I'm removing the additional information, since it is obviously wrong (thanks #Tergiver and #DeadMG for your comments). I'm also making the post community wiki, so feel free to add any additional correct information.
I have a header file in a managed DLL project like so:
Enums.h:
#pragma once
...
public ref struct ManagedStruct {
Bitmap^ image;
}
...
This header is referenced both from another class in the DLL and from a separate executable. The managed struct alone is generating:
error C2011: 'ManagedStruct' : 'class' type redefinition.
If I move the struct to the main header file in the DLL it works fine, and is publicly accessible, so that's what I'm doing, but I would very much like to learn why this is happening when I just move it to another file.
I have checked all necessary includes and namespaces AND tried the obvious header guards, to no avail; I still get the error.
Thanks very much for any insight!
You have to de-tune the traditional C/C++ header file think a bit when you work with managed code. The principal source of type declarations is the assembly metadata. This is very different from the native C/C++ compilation model where you have to have a header file for types that you make visible to other modules.
I'm going to guess that you get this C2011 error in the EXE project. Where you both added a reference to the DLL project assembly (like you should) and used #include on the header file. Like you should not. That's a guaranteed duplicate definition, #pragma once doesn't fix that.
Don't use header files for exported type definitions. Always use assembly references.
I Know this question is a bit old, but I'm writing this for future usage:
I had the following problem, which was similar:
managed DLL had a managed class.
managed.h:
namespace Managed {
ref class CManagedClass {...}
}
in an unamanged class I wanted to use this above class and so in unmanaged.h
#include "managed.h"
in another DLL I also did:
#include "unmanged.h"
which resolved in the type redefinition error.
I have found a solution to this issue using the following method:
forward declaration in the unmanaged.h
namespace Managed {
ref class CManagedClass;
}
and include the managed.h in the unmanaged.cpp file as usual.
I'm trying to call from C# a function in a custom DLL written in C++. However I'm getting the warning during code analysis and the error at runtime:
Warning: CA1400 :
Microsoft.Interoperability : Correct
the declaration of
'SafeNativeMethods.SetHook()' so that
it correctly points to an existing
entry point in 'wi.dll'. The unmanaged
entry point name currently linked to
is SetHook.
Error:
System.EntryPointNotFoundException was
unhandled. Unable to find an entry
point named 'SetHook' in DLL 'wi.dll'.
Both projects wi.dll and C# exe has been compiled in to the same DEBUG folder, both files reside here. There is only one file with the name wi.dll in the whole file system.
C++ function definition looks like:
#define WI_API __declspec(dllexport)
bool WI_API SetHook();
I can see exported function using Dependency Walker:
as decorated: bool SetHook(void)
as undecorated: ?SetHook##YA_NXZ
C# DLL import looks like (I've defined these lines using CLRInsideOut from MSDN magazine):
[DllImport("wi.dll", EntryPoint = "SetHook", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.I1)]
internal static extern bool SetHook();
I've tried without EntryPoint and CallingConvention definitions as well.
Both projects are 32-bits, I'm using W7 64 bits, VS 2010 RC.
I believe that I simply have overlooked something....
Thanks in advance.
Well, you know the entry point name, use the EntryPoint = "?SetHook##YA_NXZ" property in the [DllImport] attribute. Or put extern "C" before the declaration in your C++ code so the name doesn't get mangled.
[DllImport("wi.dll", EntryPoint = "?SetHook##YA_NXZ", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAsAttribute(UnmanagedType.I1)]
internal static extern bool SetHook();
CallingConvention.Cdecl means C not C++, so when you have a function with a C++ decorated name, you need to use the decorated name as your EntryPoint or use Extern "C" in The C++ code declaration to turn off C++ name decoration.