expose c++/CLI templated wrapper to c# - c#

I am currently working on a visual editor to build Finite State Machines. The core is c++ since the built FSM will run in a game. The editor is c#. I was able to get a CLI wrapper going so I can build everything I need in the c# side.
The last thing I am trying to do, is to be able to expose a templated class to c#.
I started by creating a managed class:
template <typename T>
public ref class TestTemp
{
private:
ClassToWrap<T>* m_val;
public:
TestTemp(T val) :
{
m_val = new ClassToWrap<T>();
}
}
Then since templates are generated at compile time, I am forcing the generation of the type with template specialization.
template ref class FSMWrapper::TestTemp<float>;
I tried to to the specialization in several places, cpp, header, also in main just in case, I even tried specific instantiation in main like this:
FSMWrapper::TestTemp<float> t(10.0f);
I even tried to explicitely tell to export the symbol like I would do in regular c++ but compiler complains that I cannot do that with a managed type.
After all this I did not managed to get the symbol appear in the c# namespace, (everything else appears, so yeah, the wrapper works as expected).
Also If I remove the template in the wrapper and just call it TestTempFloat and force internally an instantiation of float it works.
public ref class TestTempFloat
{
private:
ClassToWrap<float> m_val;
public:
TestTempFloat(float val) :
{
m_val = new ClassToWrap<float>();
}
};
What I am trying to do, is it even possible? By googling around looks like it is, but people just say, wrap it in a CLI type and force the symbol generation.
If is possible what am I doing wrong?
If is not possible I will just have to do the specialized wraps manually, not pretty but I know it works.
I also tried to wrap it in a generic instead of a template, but then I cannot feed the T generic type as a template type.
PS: I know there is not a destructor to free the memory, this is just a dummy test to keep example short.

As you have seen, managed templates aren't accessible outside of the assembly where they are located. Basically the idea is to expose the managed template as a generic interface which can be sent across assembly boundaries.
So in your case you would want to create a ITestTemp, something like this...
generic<typename T> public interface class ITestTemp
{
public:
TestTemp(T val);
}
That is the interface that you will export across assemblies. Now you will have to convert your managed template into that generic interface to do so you can use inheritance, something with the following signature (internals omitted for simplicity)
templace<typename T> ref class TestTemp : ITestTemp<T>
Once you have that now you will have to do the "compiler's work" (what is normally just automagically handled for a regular C++ template) for it to convert between the two so to speak. So you will have to create a factory method that will create the specific instances that you are looking for. It would look like this
public ref class TestTempFactory
{
public:
generic<typename T> static ITestTemp<T>^ Create()
{
if (T::typeid == String::typeid)
{ return (ITestTemp<T>^) gcnew TestTemp<String>(); }
//more cases as needed...
}
}
I hope that explains it well enough, if not let me know.

If you implement a full-fledged subclass of your template class, that should do the trick. You will need to implement all the constructors, but just as a pass-through to the base class's constructors; no actual code.
public ref class TestTempFloat : TestTemp<float>
{
TestTempFloat(float val) : TestTemp(val) { };
};
If you have a lot of these, you could make use of the preprocessor:
#define IMPLEMENT_TESTTEMP(namesuffix, type) \
public ref class TestTemp ## namesuffix : TestTemp<type> \
{ \
TestTemp ## namesuffix(type val) : TestTemp(val) { }; \
};
IMPLEMENT_TESTTEMP(Float, float)
IMPLEMENT_TESTTEMP(Double, double)
IMPLEMENT_TESTTEMP(Int, int)

Related

Why can I do a new on an interface of an Interop Assembly? [duplicate]

EDIT: I've written the results up as a blog post.
The C# compiler treats COM types somewhat magically. For instance, this statement looks normal...
Word.Application app = new Word.Application();
... until you realise that Application is an interface. Calling a constructor on an interface? Yoiks! This actually gets translated into a call to Type.GetTypeFromCLSID() and another to Activator.CreateInstance.
Additionally, in C# 4, you can use non-ref arguments for ref parameters, and the compiler just adds a local variable to pass by reference, discarding the results:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Yeah, there are a bunch of arguments missing. Aren't optional parameters nice? :)
I'm trying to investigate the compiler behaviour, and I'm failing to fake the first part. I can do the second part with no problem:
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]
public interface Dummy
{
void Foo(ref int x);
}
class Test
{
static void Main()
{
Dummy dummy = null;
dummy.Foo(10);
}
}
I'd like to be able to write:
Dummy dummy = new Dummy();
though. Obviously it'll go bang at execution time, but that's okay. I'm just experimenting.
The other attributes added by the compiler for linked COM PIAs (CompilerGenerated and TypeIdentifier) don't seem to do the trick... what's the magic sauce?
By no means am I an expert in this, but I stumbled recently on what I think you want: the CoClass attribute class.
[System.Runtime.InteropServices.CoClass(typeof(Test))]
public interface Dummy { }
A coclass supplies concrete
implementation(s) of one or more
interfaces. In COM, such concrete
implementations can be written in any
programming language that supports COM
component development, e.g. Delphi,
C++, Visual Basic, etc.
See my answer to a similar question about the Microsoft Speech API, where you're able to "instantiate" the interface SpVoice (but really, you're instantiating SPVoiceClass).
[CoClass(typeof(SpVoiceClass))]
public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }
Between you and Michael you've almost got the pieces put together. I think this is how it works. (I didn't write the code, so I might be slightly mis-stating it, but I'm pretty sure this is how it goes.)
If:
you are "new"ing an interface type, and
the interface type has a known coclass, and
you ARE using the "no pia" feature for this interface
then the code is generated as (IPIAINTERFACE)Activator.CreateInstance(Type.GetTypeFromClsid(GUID OF COCLASSTYPE))
If:
you are "new"ing an interface type, and
the interface type has a known coclass, and
you ARE NOT using the "no pia" feature for this interface
then the code is generated as if you'd said "new COCLASSTYPE()".
Jon, feel free to bug me or Sam directly if you have questions about this stuff. FYI, Sam is the expert on this feature.
Okay, this is just to put a bit more flesh on Michael's answer (he's welcome to add it in if he wants to, in which case I'll remove this one).
Looking at the original PIA for Word.Application, there are three types involved (ignoring the events):
[ComImport, TypeLibType(...), Guid("..."), DefaultMember("Name")]
public interface _Application
{
...
}
[ComImport, Guid("..."), CoClass(typeof(ApplicationClass))]
public interface Application : _Application
{
}
[ComImport, ClassInterface(...), ComSourceInterfaces("..."), Guid("..."),
TypeLibType((short) 2), DefaultMember("Name")]
public class ApplicationClass : _Application, Application
{
}
There are two interfaces for reasons that Eric Lippert talks about in another answer. And there, as you said, is the CoClass - both in terms of the class itself and the attribute on the Application interface.
Now if we use PIA linking in C# 4, some of this is embedded in the resulting binary... but not all of it. An application which just creates an instance of Application ends up with these types:
[ComImport, TypeIdentifier, Guid("..."), CompilerGenerated]
public interface _Application
[ComImport, Guid("..."), CompilerGenerated, TypeIdentifier]
public interface Application : _Application
No ApplicationClass - presumably because that will be loaded dynamically from the real COM type at execution time.
Another interesting thing is the difference in the code between the linked version and the non-linked version. If you decompile the line
Word.Application application = new Word.Application();
in the referenced version it ends up as:
Application application = new ApplicationClass();
whereas in the linked version it ends up as
Application application = (Application)
Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("...")));
So it looks like the "real" PIA needs the CoClass attribute, but the linked version doesn't because there isn't a CoClass the compiler can actually reference. It has to do it dynamically.
I might try to fake up a COM interface using this information and see if I can get the compiler to link it...
Just to add a bit of confirmation to Michael's answer:
The following code compiles and runs:
public class Program
{
public class Foo : IFoo
{
}
[Guid("00000000-0000-0000-0000-000000000000")]
[CoClass(typeof(Foo))]
[ComImport]
public interface IFoo
{
}
static void Main(string[] args)
{
IFoo foo = new IFoo();
}
}
You need both the ComImportAttribute and the GuidAttribute for it to work.
Also note the information when you hover the mouse over the new IFoo(): Intellisense properly picks up on the information: Nice!

How can I decrease verbosity when inheriting from C# generic types to non-generic types?

With C# generics (specifically, type parameters for classes), is it possible to refer to specified type parameter values in an specialized ("non-generic") type (class) that extends/inherits the generic one? In this case, I'm overriding virtual methods of the generic (inherited) type in the inheriting (specialized) one; I suspect that's important to the question/answer, but don't want to limit the case if not.
I might just be looking for what C calls a typedef; the closest thing I can think of in C# is a using alias (using Type = Some.Longer.Namespaced.Type;). Here is an example w/ the using alias, but even this is still very verbose and is no fun to update when e.g. the name of ConcreteType changes (or some other refactor, where the boundaries/encapsulations of logic shift, not the logic itself):
using ConcreteType = Some.Longer.Namespaced.Type;
public class ConcreteTypeLogic : CrudLogic<ConcreteType>
{
// default ctor for `ConcreteTypeLogic`
public ConcreteTypeLogic()
{ /* ... */ }
// other ctor for `ConcreteTypeLogic`
/* ... */
// dtor for `ConcreteTypeLogic`
public ~ConcreteTypeLogic()
{ /* ... */ }
// "Create" implementation for `ConcreteType`
public override ConcreteType Create(ConcreteType value)
{ /* ... */ }
// "Read" implementation for `ConcreteType`
public override ConcreteType Read(ConcreteTypeIdentifier valueId)
{ /* ... */ }
/* ... */
}
It seems like a C-style typedef or a CPP-style macro is really what I want though, because ConcreteTypeLogic and the constructor/destructor will need to update as well, as well as any other relevant aspects where the type (class) name is part of the binding/contract.
Outside of the using alias, the language (C#) doesn't support this naming indirection.
It's not common to use a pre-processor when building C# (.NET) projects, and the common alternative is to use development tools to expedite this "work." Considering that the definition of a type doesn't need to reside in a single source file, or even a single assembly, development tooling seems the best approach to managing this.
Thanks to the commenters for their responses.

Is dependency injection useful in C++

C# uses Dependency Injection (DI) a lot to have a lossless and testable platform. For this, I need an interface and maybe a DI or Inversion of Control (IoC) container for resolving my instances.
But how do you do this in C++? I've read a little bit about this, and it seems that dependency injection in C++ isn't as big a topic as in C#. In C++ you use a reference to an object - this is the way to use DI in C++, right?
If my theory with references are correct, is there something like a container where I can resolve all the references? In C# I have a "bad class/bad project/assembly" which registers all my instances into a static container at the program start. Then, in every class, I'm able to instance the static container and can resolving a specific instance, is this possible in C++?
Are you using Dependency Injection (or whatever it is called) in C++? If yes, how you're use it? Are there similarities to C#?
For this, I need an interface and maybe a container for resolving my instances. But how you do this in C++?
In the same way. The difference is that where you "program to an interface" in C#, you "program to a base class" in C++. Additionally, you have extra tools in C++ that you do not have in C# (for example, policy-based templates implement dependency injection chosen at compilation time).
In C++ you're use a reference to an object, this is the way to use DI in C++, right?
No; this is not the way to use DI, this is a way to use DI in C++.
Also consider:
use a pointer to an object (or smart pointer, depending on the case)
use a template argument for a policy (for an example, see std::default_delete use in smart pointers)
use lambda calcullus with injected functors/predicates.
In C# I've a "bad class/bad project/assembly" which register all my instance into a static container at the program start.
If I understand correctly, you set all your data in this static container and use it all over the application. If this is the case, then you do not use dependency injection correctly, because this breaks Demeter's Law.
is this possible in C++?
Yes, it is perfectly possible (but you shouldn't do it, due to it breaking Demeter's law). Have a look at boost::any (this will allow you to store heterogenous objects in a container, similar to storing objects by object reference in C#).
Are you using dependency injection or whatever it is called in C++?
Yes (and it is called dependency injection :) ).
If yes, how you're use it?
As I described above (policy template arguments, injected functors and predicates as reusable components, injecting objects by reference, pointer smart pointer or value).
With C++11 as a project limit I ended up rolling my own. I loosely based it on .NET Ninject API without the Reflection ofcourse.
ServiceLocator
Note, although its called ServiceLocator (since it does not do Dependancy Injection itself) if you use lambda function bindings and preferably ServiceLocator::Module classes you get Injection (not reflection based) and it works really really well (IMO)
#include <iostream>
#include <vector>
#include "ServiceLocator.hpp"
template <class T>
using sptr = std::shared_ptr<T>;
// Some plain interfaces
class IFood {
public:
virtual std::string name() = 0;
};
class IAnimal {
public:
virtual void eatFavouriteFood() = 0;
};
// Concrete classes which implement our interfaces, these 2 have no dependancies
class Banana : public IFood {
public:
std::string name() override {
return "Banana";
}
};
class Pizza : public IFood {
public:
std::string name() override {
return "Pizza";
}
};
// Monkey requires a favourite food, note it is not dependant on ServiceLocator
class Monkey : public IAnimal {
private:
sptr<IFood> _food;
public:
Monkey(sptr<IFood> food) : _food(food) {
}
void eatFavouriteFood() override {
std::cout << "Monkey eats " << _food->name() << "\n";
}
};
// Human requires a favourite food, note it is not dependant on ServiceLocator
class Human : public IAnimal {
private:
sptr<IFood> _food;
public:
Human(sptr<IFood> food) : _food(food) {
}
void eatFavouriteFood() override {
std::cout << "Human eats " << _food->name() << "\n";
}
};
/* The SLModule classes are ServiceLocator aware, and they are also intimate with the concrete classes they bind to
and so know what dependancies are required to create instances */
class FoodSLModule : public ServiceLocator::Module {
public:
void load() override {
bind<IFood>("Monkey").to<Banana>([] (SLContext_sptr slc) {
return new Banana();
});
bind<IFood>("Human").to<Pizza>([] (SLContext_sptr slc) {
return new Pizza();
});
}
};
class AnimalsSLModule : public ServiceLocator::Module {
public:
void load() override {
bind<IAnimal>("Human").to<Human>([] (SLContext_sptr slc) {
return new Human(slc->resolve<IFood>("Human"));
});
bind<IAnimal>("Monkey").to<Monkey>([] (SLContext_sptr slc) {
return new Monkey(slc->resolve<IFood>("Monkey"));
});
}
};
int main(int argc, const char * argv[]) {
auto sl = ServiceLocator::create();
sl->modules()
.add<FoodSLModule>()
.add<AnimalsSLModule>();
auto slc = sl->getContext();
std::vector<sptr<IAnimal>> animals;
slc->resolveAll<IAnimal>(&animals);
for(auto animal : animals) {
animal->eatFavouriteFood();
}
return 0;
}
Using dependency injection is quite straightforward in C++. Just define an interface (a pure abstract base class) that you use as reference or pointer (or smart pointer) argument to the constructor or init function of the class you want to dependency inject into.
Then, in the unit test, inject a mock object (an instance of a class inheriting from the abstract interface class), and in real code, inject an instance of the real class (also inheriting from the same interface class).
Easy-peasy.
Yes, dependency injection is useful in C++ as well. There is no reason why it shouldn´t be, because it doesn´t require a specific language or syntax, but just an object-oriented class architecture (at least this is probably the most usual case).
While in C# there are only "pointers" to dynamically allocated objects, C++ has multiple variants, like "normal" local variables, multiple kind of pointers, references... additionally the concept of move semantics is very relevant to this.
In C++ you're use a reference to an object, this is the way to use DI
in C++, right?
Not only. You can use whatever you want as long you can pass something to a class method and this something will exist as long as the class object does. All of the three possibilites above can do that (each of them with certain restrictions)
is there something like a container were I can resolve all this
references? In C# I've a "bad class/bad project/assembly" which
register all my instance into a static container
Maybe you´re missing the point of dependeny injection. It´s not the same as a bunch of "global" variables. But yes, of course this is possible in C++ too. There are classes, there is static, and that´s everything needed.
If my theory with references are correct, is there something like a container where I can resolve all the references? In C# I have a "bad class/bad project/assembly" which registers all my instances into a static container at the program start. Then, in every class, I'm able to instance the static container and can resolving a specific instance, is this possible in C++?
That's not how DI is supposed to be used, you don't pass your container to all your "consumer" class. In a well designed application you just do few resolve in the entry point and that's it. Most of the time the need for a "resolve" can be replaced by the use of a factory which will be registered then injected.
You'll have a lot of trouble testing code depending on a static class. I would recommend if you really want to inject your container in your client class to at least instance and inject it, static dependencies are hell, would be easier to mock for unit testing.

.NET vb6 wrapper property with parameter

i need to write a c# wrapper for a vb6 application. I always get error 450 ( Wrong number of arguments or property assignment was not valid.) This is my VB Code
Dim DBEngine As New DBEngineNet
Set mDbEProp = DBEngine.Properties("Version") ' <-- ERROR
This code is working, so the problem is the parameter of the property
Dim DBEngine As New DBEngineNet
Set mDbEProps = DBEngine.Properties
Set mDbEProp = mDbEProps("Version") '<-- Working. Results 1.0
Here is my COM-Visible C#-Code. It uses the Interop-Interfaces of the old VB6-MotorApp.
[ComVisible(true)]
public class DBEngineNet : VB6MotorApp.DBEngine
{
public VB6MotorApp.Properties Properties
{
// [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_SAFEARRAY)] Maybe something like this???
get
{
return new PropertiesNet
{
new PropertyNet{Name="Version", Value="1.0"}
};
}
}
Here is the Properties-Object:
[ComVisible(true)]
public class PropertiesNet : VB6MotorApp.Properties, IList<PropertyNet>
{
List<PropertyNet> _properties = new List<PropertyNet>();
public VB6MotorApp.Property this[object Item]
{
get
{
return _properties.FirstOrDefault(p => p.Name == Item.ToString());
}
}
}
Any ideas?
The basic diagnostic tool you need here is OleView.exe, run it from the Visual Studio Command Prompt. Use its File + View typelib command to look at the type libraries and compare them. First on your original VB6 implementation so you have a base-line, next on the type library for your .NET version.
There are inevitably going to be major difference the way you are doing it now, you are exposing too many details of the class implementation. All of the System.Object methods as well as the IList<> implementation methods are going to be visible. Boilerplate is to declare a [ComVisible(true)] interface (VB6 likes their name to start with an _underscore) and hide the class implementation by giving it the [ClassInterface(ClassInterfaceType.None)] attribute. You already have the interface so only the attribute should be necessary.
What you want to look for first in the OleView.exe output is the [dispid] attribute for the DBEngineNet.Properties property. It doesn't act like the default property which is why you have to obtain the property value explicitly in your VB6 code. The default property has dispid(0). You force the value in .NET code by giving it the [DispId(0)] attribute.
You also want to look at the original type library, "VB6MotorApp.Properties" looks wrong. That's a coclass name, not an interface name. Non-zero odds that you should be using VB6MotorApp._Properties. Same for VB6MotorApp._DBEngine.
And look at which interfaces in the coclasses have the [default] attribute. It should be the VB6 interfaces. Probably not an issue if your VB6 snippets work as posted.

Automatic (and not refactor-related) extraction of interface from class

I'm relatively new to C# so this may be a somewhat naive question.
Does there exist a way, or can one even be constructed, to construct an interface containing all the public methods/properties of a class?
I find myself in a project using the mocking framework Moq. Moq has an apparently rather common limitation in that it can only handle interfaces and virtual methods. The project's architect has decided to go the interface route, which means every class in the project has an accompanying interface. This means there are loads of interfaces implemented by a single class. Furthermore, the style mandates that interfaces go into their own files. This means there are loads of files in the project.
In my opinion it would be a real improvement if these interface-and-files-just-for-Moq could be a bit less intrusive. Is there no way to have the system (Visual Studio/.Net/C#) create them.
For instance, if writing this
[ExtractAndImplement("IFoo")]
public class Foo
{
public int Bar(int baz)
{
...
}
}
would be equivalent to
public interface IFoo
{
int Bar(int baz);
}
public class Foo : IFoo
{
public int Bar(int baz)
{
...
}
}
NB No, Refactor -> Extract Interface does not do what I want. First off, it creates an interface in source code somewhere, so it doesn't reduce the clutter of singly-implemented interfaces. Second, it's an interface I need to maintain explicitly; when I add a public method in the class I need to extract that new method to the correct interface. No, I'd like to have something that's implicit, i.e. interfaces are created on the fly without cluttering the source or the project.
I'm guessing that in Lisp/Scheme it'd be done using macros, and in Haskell using templates.
You can do this in Visual Studio (not in the express version).
Use Refactor -> Extract Interface. The cursor needs to be placed on the classname.
For more information:
http://msdn.microsoft.com/en-us/library/fb3dyx26.aspx
You could also look at ReSharper for this option or SharpDevelop.
You are probably asking for
The interface language is in Italian (It says "Extract Interface"), sorry, but you got a hint I hope.

Categories

Resources