I'm running into a very strange problem trying to compile and use a windows runtime component within an UWP application (VS2017 community 15.9.13 with NetCore.UniversalWindowsPlatform 6.2.8, compiled without /clr but with /ZW).
It is basically something like the Grayscaletransform. The runtime component is actually working as expected, now I wanted to remove some unused code. However, as soon as I remove it from a particular file and recompile, it indeed compiles, links, but the DLL does not load any more.
Here's some example code that I have to put in:
ref class DummyU sealed
{
public:
DummyU() {}
};
DummyU^ CreateDummyU()
{
return ref new DummyU();
}
The code just makes it work, although it is a) not referenced at all and b) does not do anything useful.
The result of removing it:
Exception thrown at 0x0EFF322F (vccorlib140d_app.dll) in TestAppUWP.exe: 0xC0000005: Access violation reading location 0x00000000.
in
STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _Deref_out_ IActivationFactory** ppFactory)
{
return Platform::Details::GetActivationFactory(Microsoft::WRL::Details::ModuleBase::module_, activatibleClassId, ppFactory);
}
function in dllexports.cpp which is part of VS. The module_ becomes NULL.
Does anyone have an idea if there are any known bugs with respect to the windows runtime not being initialized/used properly if there is no explicit instantiation of a ref class in a file?
EDIT 1:
Here's the link to the full source code:
What's happening here is that you're mixing modes a bit. Since you've compiled your C++ code with the /CX flag, you've told the compiler to enable winrt extensions to produce a WinRT DLL. In practice though, none of your code is actually using the CX extensions to implement classes. You're using WRL and standards C++. The compiler looks at the DLL, finds no CX-style WinRT classes, and doesn't set up the module, accordingly.
This is basically an untested & unsupported case, since you've chosen to say that you want to expose ref classes by picking a UWP component library project type, but then didn't actually provide any ref classes. It happens that under the hood, /CX effectively uses WRL, so you can nudge it along and initialize the state to work correctly, but you're kinda hacking the implementation details of the system.
There are two options I would recommend, either works: just make the project a non-CX Win32 DLL and init the module as described above. Or, better yet, flip over to C++ /WinRT, which will give you better support for the WinRT types than /CX and allow you to more easily mix in the classic COM types in your implementation. You can get started by just turning off the /CX flag in the compiler switches, then start updating the code accordingly.
Ben
You might have wrong .winmd file for your component. WinRT components made in C++ produce two outputs, dll and winmd. Both must match. It's possible you have them from different builds.
Another possible reason is error in manifest. The manifest of the app must include all referenced runtime components.
BTW, for native DLLs written in classic C++ and exposing C API, deployment is simpler, you include a DLL in the package and they just work, with [DllImport] if you're consuming them from C#.
Update: You can replace that ref class with the following code, works on my PC.
struct ModuleStaticInitialize
{
ModuleStaticInitialize()
{
Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
}
};
static ModuleStaticInitialize s_moduleInit;
Probably a bug in Microsoft's runtime somewhere.
Related
Now, I implemented a factory class to dynamically create class with a idenification string, please see the following code:
void IOFactory::registerIO()
{
Register("NDAM9020", []() -> IOBase * {
return new NDAM9020();
});
Register("BK5120", []() -> IOBase * {
return new BK5120();
});
}
std::unique_ptr<IOBase> IOFactory::createIO(std::string ioDeviceName)
{
std::unique_ptr<IOBase> io = createObject(ioDeviceName);
return io;
}
So we can create the IO class with the registered name:
IOFactory ioFactory;
auto io = ioFactory.createIO("BK5120");
The problem with this method is if we add another IO component, we should add another register code in registerIO function and compile the whole project again. So I was wondering if I could dynamically register class from a configure file(see below) at runtime.
io_factory.conf
------------------
NDAM9020:NDAM9020
BK5120:BK5120
------------------
The first is identification name and the second is class name.
I have tried with Macros, but the parameter in Macros cann't be string. So I was wondering if there is some other ways. Thanks for advance.
Update:
I didn't expect so many comments and answers, Thank you all and sorry for replying late.
Our current OS is Ubuntu16.04 and we use the builtin compiler that is gcc/g++5.4.0, and we use CMake to manage the build.
And I should mention that it is not a must that I should register class at runtime period, it is also OK if there is a way to do this in compile period. What I want is just avoiding the recompiling when I want to register another class.
So I was wondering if I could dynamically register class from a configure file(see below) at runtime.
No. As of C++20, C++ has no reflection features allowing it. But you could do it at compile time by generating a simple C++ implementation file from your configuration file.
How to dynamically register class in a factory class at runtime period with c++
Read much more about C++, at least a good C++ programming book and see a good C++ reference website, and later n3337, the C++11 standard. Read also the documentation of your C++ compiler (perhaps GCC or Clang), and, if you have one, of your operating system. If plugins are possible in your OS, you can register a factory function at runtime (by referring to to that function after a plugin providing it has been loaded). For examples, the Mozilla firefox browser or recent GCC compilers (e.g. GCC 10 with plugins enabled), or the fish shell, are doing this.
So I was wondering if I could dynamically register class from a configure file(see below) at runtime.
Most C++ programs are running under an operating system, such as Linux. Some operating systems provide a plugin mechanism. For Linux, see dlopen(3), dlsym(3), dlclose(3), dladdr(3) and the C++ dlopen mini-howto. For Windows, dive into its documentation.
So, with a recent C++ implementation and some recent operating systems, y ou can register at runtime a factory class (using plugins), and you could find libraries (e.g. Qt or POCO) to help you.
However, in pure standard C++, the set of translation units is statically known and plugins do not exist. So the set of functions, lambda-expressions, or classes in a given program is finite and does not change with time.
In pure C++, the set of valid function pointers, or the set of valid possible values for a given std::function variable, is finite. Anything else is undefined behavior. In practice, many real-life C++ programs accept plugins thru their operating systems or JIT-compiling libraries.
You could of course consider using JIT-compiling libraries such as asmjit or libgccjit or LLVM. They are implementation specific, so your code won't be portable.
On Linux, a lot of Qt or GTKmm applications (e.g. KDE, and most web browsers, e.g. Konqueror, Chrome, or Firefox) are coded in C++ and do load plugins with factory functions. Check with strace(1) and ltrace(1).
The Trident web browser of MicroSoft is rumored to be coded in C++ and probably accepts plugins.
I have tried with Macros, but the parameter in Macros can't be string.
A macro parameter can be stringized. And you could play x-macros tricks.
What I want is just avoiding the recompiling when I want to register another class.
On Ubuntu, I recommend accepting plugins in your program or library
Use dlopen(3) with an absolute file path; the plugin would typically be passed as a program option (like RefPerSys does, or like GCC does) and dlopen-ed at program or library initialization time. Practically speaking, you can have lots of plugins (dozen of thousands, see manydl.c and check with pmap(1) or proc(5)). The dlsym(3)-ed C++ functions in your plugins should be declared extern "C" to disable name mangling.
A single C++ file plugin (in yourplugin.cc) can be compiled with g++ -Wall -O -g -fPIC -shared yourplugin.cc -o yourplugin.so and later you would dlopen "./yourplugin.so" or an absolute path (or configure suitably your $LD_LIBRARY_PATH -see ld.so(8)- and pass "yourplugin.so" to dlopen). Be also aware of Rpath.
Consider also (after upgrading your GCC to GCC 9 at least, perhaps by compiling it from its source code) using libgccjit (it is faster than generating temporary C++ code in some file and compiling that file into a temporary plugin).
For ease of debugging your loaded plugins, you might be interested by Ian Taylor's libbacktrace.
Notice that your program's global symbols (declared as extern "C") can be accessed by name by passing a nullptr file path to dlopen(3), then using dlsym(3) on the obtained handle. You want to pass -rdynamic -ldl when linking your program (or your shared library).
What I want is just avoiding the recompiling when I want to register another class.
You might registering classes in a different translation unit (a short one, presumably). You could take inspiration from RefPerSys multiple #include-s of its generated/rps-name.hh file. Then you would simply recompile a single *.cc file and relink your entire program or library. Notice that Qt plays similar tricks in its moc, and I recommend taking inspiration from it.
Read also J.Pitrat's book on Artificial Beings: the Conscience of a Conscious Machine ISBN which explains why a metaprogramming approach is useful. Study the source code of GCC (or of RefPerSys), use or take inspiration from SWIG, ANTLR, GNU bison (they all generate C++ code) when relevant
You seem to have asked for more dynamism than you actually need. You want to avoid the factory itself having to be aware of all of the classes registered in it.
Well, that's doable without going all the way runtime code generation!
There are several implementations of such a factory; but I am obviously biased in favor of my own: einpoklum's Factory class (gist.github.com)
simple example of use:
#include "Factory.h"
// we now have:
//
// template<typename Key, typename BaseClass, typename... ConstructionArgs>
// class Factory;
//
#include <string>
struct Foo { Foo(int x) { }; }
struct Bar : Foo { Bar(int x) : Foo(x) { }; }
int main()
{
util::Factory<std::string, Foo, int> factory;
factory.registerClass<Bar>("key_for_bar");
auto* my_bar_ptr factory.produce("key_for_bar");
}
Notes:
The std::string is used as a key; you could have a factory with numeric values as keys instead, if you like.
All registered classes must be subclasses of the BaseClass value chosen for the factory. I believe you can change the factory to avoid that, but then you'll always be getting void *s from it.
You can wrap this in a singleton template to get a single, global, static-initialization-safe factory you can use from anywhere.
Now, if you load some plugin dynamically (see #BasileStarynkevitch's answer), you just need that plugin to expose an initialization function which makes registerClass() class calls on the factory; and call this initialization function right after loading the plugin. Or if you have a static-initialization safe singleton factory, you can make the registration calls in a static-block in your plugin shared library - but be careful with that, I'm not an expert on shared library loading.
Definetly YES!
Theres an old antique post from 2006 that solved my life for many years. The implementation runs arround having a centralized registry with a decentralized registration method that is expanded using a REGISTER_X macro, check it out:
https://web.archive.org/web/20100618122920/http://meat.net/2006/03/cpp-runtime-class-registration/
Have to admit that #einpoklum factory looks awesome also. I created a headeronly sample gist containing the code and a sample:
https://gist.github.com/h3r/5aa48ba37c374f03af25b9e5e0346a86
We have a large MFC application that is in the process of being updated. It has been modified to add in some .NET components (some of the DLLs now have managed & native classes), the idea is that the old code will be phased out eventually.
The app has many DLLs with native C++ classes exported, and used by the application.
On trying to test the app we now find ANY exception seems to cause the app to crash, even though these exceptions are in theory being caught in the same function.
example:
CString AddressClass::GetPostalAddress()
{
CString address;
try {
address = (LPCSTR)(_bstr_t)m_pCommand->GetParameters()->Item["PostalAddress"]->Value;
}
catch ( _com_error& )//exception occurs if postal address is NULL
{
address = _T("");
}
return address;
}
The _com_error is not being caught when compiling with /clr and /EHa (Vs2015 update 3). Without /clr it works fine and has been operational for years. From the documentation I have read my understanding is this should work, but clearly I am mistaken.
The code responsible for generating the error is in comutil.h:
inline void CheckError(HRESULT hr)
{
if (FAILED(hr)) {
_com_issue_error(hr);
}
}
The information from the debugger is:
An exception of type 'System.Runtime.InteropServices.SEHException' occurred in XXX.dll and wasn't handled before a managed/native boundary
Additional information: External component has thrown an exception.
Is there anyway to get this working without rewriting huge amounts of code?
Thanks.
Answer from short comment, since it seems to have helped:
Generally speaking: You should not compile these with /clr. Separate your old code vs your new CLR-using code, just compile new code with /clr, compile old code/files directly native. You can still link everything together in a clr-enabled DLL.
What we do is to compile all the native stuff in separate static LIB projects, and then link these into /clr enabled projects - having separate compiler switches for individual source files inside one project is always a tad confusing. But then, it may still be the way to go for you. Depends on the mixture and calling patterns, I guess.
I'll add that I view /clr mostly as a rather powerful glue system, than something you should target for the full app stack.
I have the following setup:
CSharp.dll, a C# dll
CppCli.dll, a Mixed-Mode C++/Cli dll.
Native.dll, a native C++ dll.
The native project declares
class Native
{
public:
virtual void Add(int a);
};
which is implemented in the mixed mode project:
class Mixed : public Native
{
public:
virtual void Add(int a);
ICSharpInterface^ MakeManaged();
};
Since the base class is defined in Native, I can pass my implementation to other code in native. But now I want to test this class.
If I use #pragma make_public(Mixed); it will only make a struct public, without any functions visible to the outside.
If I try to link to the mixed-mode dll from another mixed-mode dll, I get linker errors because it's a native class and the mixed-mode dll generates no .lib to link against.
And if I try to __declspec(dllexport) the class, the Visual Studio complains because the interface exposes managed stuff.
So my question is:
How do I instantiate (link to) this class in my tests? I would be happy with any solution that shows how to create an instance where I can call its public interface on, doesn't matter if from C++, C++/Cli or from C#.
You are missing an important step, you haven't yet considered how a native program is going to create an instance of the Mixed object. Which is non-trivial, it does require getting the CLR loaded and initialized so it can execute managed code. Keep in mind that the client code does not do this automatically, it doesn't know beans about the CLR, it only knows about Native.dll. There are three basic ways to get this done:
You can expose managed classes as COM objects, very simple to do with the [ComVisible] attribute. Possible to do directly from C#, you don't need the C++/CLI wrapper. The usual disadvantage is that the client code has to use COM to instantiate the object and make calls on it, not the kind of code that programmers like to write.
You can host the CLR yourself, the most efficient and flexible solution. This magazine article gives an introduction, beware that it is dated.
The C++/CLI compiler gives you a way to give you an unmanaged exported function that can execute managed code. It auto-generates a stub that gets the CLR loaded and initialized, if necessary.
Focusing a bit on the last bullet, since that's what you probably like, what you need here is a factory function, one that creates an instance of the Mixed class and returns a Native* back to the caller. So it can call ptr->Add() and invoke Mixed::Add(). That can look like this:
extern "C" __declspec(dllexport)
Native* CreateObject() {
return new Mixed;
}
Also gets you the import .lib that you can link in your native project. Do beware the disadvantages, they are significant. It is not exactly fast since the stub must check if the CLR is initialized yet and make the native-to-managed transition. The error reporting is extremely lousy since you have no decent way to diagnose exceptions that are thrown in the C# code. And memory management is an issue, the caller has to be able to successfully destroy the returned object which requires all modules to use the exact same CRT. The kind of problems that COM solves.
The exact same technique is available in C# as well by using an IL rewriter. Gieseke's unmanaged exports template is popular.
I have inherited an old MFC/Win32 C++ application who's source code I am not supposed to edit.
This MFC application needs to host an old MFC/Win32 C++ DLL. This DLL also tries to make function calls through a Mixed-mode wrapper to a managed C++/CLI DLL. I know it sounds a little confusing, so here's a diagram of what I mean:
Old MFC/Win32 Application (NO CLR)
---> Hosting old MFC/Win32 DLL (NO CLR)
---> Making function calls to Mixed-Mode wrapper (CLR)
---> Sending function calls to C++/CLI DLL (CLR)
My problem currently is that when I try to mount an object of the C++/CLR wrapper class let's say WrapperClass WC;, the MFC/Win32 application encounters an "Unhandled exception."
I have a feeling that I may need to somehow host the CLR in a separate process in order to be able to make the object. Is this the right idea? Or am I completely out of whack here?
The code compiles time and this only occurs at run-time.
Any ideas?
Here is an example of the code I am trying to run:
MFC/Win32 DLL
#include "WrapperClass.h"
BOOL Test::bTest() //This function is called elsewhere within MFC/Win32 DLL
{
DWORD dwTest;
WrapperClass WC; //Unhandled exception here!
return WC.FunctionToCall(dwTest); //FunctionToCall is a BOOL
}
Mixed-Mode Wrapper Class
BOOL WrapperClass::FunctionToCall(DWORD dw)
{
GCHandle h = GCHandle::FromIntPtr(IntPtr(m_impl)); //m_impl def'd as void *
CPPCLIClass^ CCC = safe_cast<CPPCLIClass^>(h.Target);
return (BOOL)CCC->FunctionToCall(dw);
}
C++/CLI DLL
bool CPPCLIClass::FunctionToCall(UInt32 ui32)
{
if (ui32 == 42)
{
return true;
}
}
UPDATE:
I've managed to coax a real exception out of the program. I am now receiving a System.IO.FileNotFound exception with additional information stating:
An unhandled exception of type 'System.IO.FileNotFoundException' occured in
Unknown Module.
Additional information: Could not load file or assembly 'CPPCLIProject,
Version=1.0.4351.29839, Culture=neutral, PublicKeyToken=null' or one of its
dependencies. The system cannot find the file specified.
Does this mean anything? I understand that it apparently cannot find CPPCLIProject (Note: this is not the wrapper project), but then if I'm linking on the .lib file from the Mixed-mode wrapper, how would I not receive linker errors then?
Are you sure that the implementation of WrapperClass::FunctionToCall() isn't throwing the exception? It looks like you're caching the memory location of a CLR object, and then trying to call one of its members. I think the CLR is free to move objects around, so it's possible that you're trying to use an object that has moved.
If you change the implementation of WrapperClass::FunctionToCall() to something simple (i.e. create a CLR object, call a member function), do you still get the same unhandled exception?
UPDATE: Which class is in CPPCLIProject - CPPCLIClass? Assuming this project represents the C++/CLI DLL, it sounds like it just can't find the assembly to load it when it needs to call your class.
Where is this assembly on disk relative to the rest of the application? If your root EXE is unmanaged (which it sounds like it is, since it is MFC/Win32), then the CLR looks in the EXE's directory and the GAC in order to load assemblies (I don't think it looks in the Path, but I'm not positive on that).
So if the CPPCLIProject isn't in the same directory as the EXE, that could be your problem.
Your best bet is to
run under a debugger (add the additional DLLs with debug information to the debug session)
enable break on all (first-chance) exceptions
trace/assert all HRESULT codes
in general try to catch
C++ exceptions (try/catch...)
Windows Structured Exceptions (IIRC _try/_catch, but see MSDN)
The idea is to convert the 'unkown exception' into 'known exception'.
Normally speaking there is no need to host the CLR part out of process. This is what a mixed-mode DLL is about. Then again, if this is legacy code, you might be running into complicated mixes of runtime dependencies that, shall we say, could clash.
Further thoughts:
If I understand correctly, you have the option to recompile all sources (just not touch the legacy codebase?). If so, make sure all code is compiled against the same version (think Service Packs) and type (think Static vs Dynamic/Multithread/Debug) of the runtime libraries.
While you are checking additional pathways, keep an eye on potentially conflicting dependencies on
ATL server libs
MFC libs (again static vs dynamic/Multithread/Debug flavours).
My executable makes calls to a number of DLLs, that i wrote myself. According to 3rd party C++ libs used by these DLLs i can not freely choose compiler settings for all DLLs. Therefore in some DLLs _ITERATOR_DEBUG_LEVEL is set to 2 (default in the debug version), but in my executable _ITERATOR_DEBUG_LEVEL is set to 0, according to serious performance problems.
When i now pass a std::string to the DLL, the application crashes, as soon as the DLL tries to copy it to a local std::string obj, as the memory layout of the string object in the DLL is different from that in my executable. So far i work around this by passing C-strings. I even wrote a small class that converts a std::map<std::string, int> to and from a temporary representation in C-Data in order to pass sich data from and to the DLL. This works.
How can i overcome this problem? I want to pass more different classes and containers, and for several reasons i do not want to work with _ITERATOR_DEBUG_LEVEL = 2.
The problem is that std::string and other containers are template classes. They are generated at compilation time for each binary, so in your case they are generated differently. You can say it's not the same objects.
To fix this, you have several solutions, but they are all following the same rule of thumb : don't expose any template code in your header code shared between binaries.
You could create specific interfaces only for this purpose, or just make sure your headers don't expose template types and functions. You can use those template types inside your binaries, but just don't expose them to other binaries.
std::string in interfaces can be replaced by const char * . You can still use std::string in your systems, just ask for const char * in interfaces and use std::string::c_str() to expose your data.
For maps and other containers you'll have to provide functions that allow external code to manipulate the internal map. Like "Find( const char* key ); ".
The main problem will be with template members of your exposed classes. A way to fix this is to use the PImpl idiom : create (or generate) an API, headers, that just expose what can be done with your binaries, and then make sure that API have pointers to the real objects inside your binaries. The API will be used outside but inside your library you can code with whatever you want. DirectX API and other OS API are done that way.
It is not recommended to use an c++ interface with complex types (stl...) with 3rd party libs, if you get them only as binary or need special settings for compile which are different from your settings.
As you wrote - the implementation could be different with the same compiler depending on your settings and with different compilers the situation gets even worse.
If possible compile the 3rd party lib with your compiler and your settings.
If that's not possible you may write an wrapper-DLL which is compiled with the same compiler and same settings than the 3rd party lib and provides an C-Data interface for you. In your project you may write another wrapper-class so you can make your function-calls with STL-Objects and get them converted and transfered "in background".
My own experience with flags like _SECURE_SCL and _ITERATOR_DEBUG_LEVEL, is that they must be consistent if you attempt to pass a stl object accross dll boudaries.
However I think you can pass a stl object to a dll which has a smaller _ITERATOR_DEBUG_LEVEL
since you can probably give a stl object instantiated in a debug dll to a dll compiled in release mode.
EDIT 07/04/2011
Apparently Visual Studio 2010 provides some niceties to detect mismatches between ITERATOR_DEBUG_LEVEL. I have not watch the video yet.
http://blogs.msdn.com/b/vcblog/archive/2011/04/05/10150198.aspx