I have a C# event handler that I would like to C++/CLI, but I have been unable to find any similar handles online. I would like to keep the structure somewhat similar if possible. Is there any documentation or similar functionaly it in C++/CLI?
Here is the C# event:
private void SubEvent<TEvent, TPayload>(SubscriptionToken token, Action<TPayload> payload, ThreadOption threadOption, bool foo)
where TEvent : PubSubEvent<TPayload>, new()
{
//do stuff
}
There's nothing in that method signature that doesn't have a direct equivalent in C++/CLI. You should be able to do the exact same thing in C++/CLI as you're doing in C#.
private:
generic<typename TEvent, typename TPayload> where TEvent : PubSubEvent<TPayload>, gcnew()
void SubEvent(SubscriptionToken^ token, Action<TPayload>^ payload, ThreadOption threadOption, bool foo)
{
//do stuff
}
Related
I am working on a Outlook addin in which I want to send the data from one outlook addin project to another outlook project. But when I try call the function of another project with the object type data in the arguments it will throw "Unable to cast object of type 'System.Runtime.Remoting.Proxies.__TransparentProxy' to type at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)" error.
Here is the code for your reference.
public IProfileAttribute[] profileAttributes= null;
Outlook.Application outlookApp = new Outlook.Application();
this.profileAttributes = new FilingNotifiableIpmlementation().FilingNotification(); // to fill the object
object destAddinName = "Tikit.CarpeDiem.AddIn.Outlook";
Office.COMAddIn destAddIn = outlookApp.COMAddIns.Item(ref destAddinName)
destAddIn.Object.FilingNotification(this.profileAttributes);
FilingNotification() is the method which we want to call of Tikit.CarpeDiem.AddIn.Outlook this project and this.profileAttributes is the object array.
The flow is going perfectly to the Outlook project if the parameter type is either string or int but it is throwing error if the parameter is object type.
Implementation of FilingNotification() method in Tikit.CarpeDiem.AddIn.Outlook project.
public void FilingNotification(IProfileAttribute[] profileAttributesList)
{
if (profileAttributesList != null)
{
var x = profileAttributesList;
}
else
{
string y = "Try again";
}
}
Can someone help me in this one. I am stuck in this for 2 days. It will be really helpful. Thanks in advance.
Instead of passing a .Net object, make it implement a COM interface and pass it as an interface:
var obj = new MyBlah();
destAddIn.Object.FilingNotification(obj as IBlah);
...
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IBlah
{
void DoBlah();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class MyBlah: StandardOleMarshalObject, IBlah
{
public void DoBlah()
{
//todo
};
}
You may pass scalar data types following that way. You need to implement an interface known on both sides if you want to pass objects between two entities. Read more about that in the Walkthrough: Call code in a VSTO Add-in from VBA article. For example:
[ComVisible(true)]
public interface IAddInUtilities
{
void ImportData();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class AddInUtilities : IAddInUtilities
{
// This method tries to write a string to cell A1 in the active worksheet.
public void ImportData()
{
// implementation
}
}
Also you may consider using any standard mechanisms available for .net based applications such Remoting or WCF, see Basic WCF programming for more information.
I`m trying to implement something like this using C++11.
class Proto{
public:
virtual void fu() = 0;
};
class Impl: public Proto{
public:
void fu();
};
void Impl::fu(){
LOG_INFO("im fu");
}
class Inv{
public:
void useFu(void (Proto::*)());
};
void Inv::useFu(void (Proto::*fu)()){
//fu();
};
void main(){
Impl impl;
Inv inv;
//inv.useFu(impl.fu);
}
useFu(void (Proto::*)()) must be declared in this way because, fu() uses some specific to Proto functionality's
I have two places were things going wrong.
First is fu() call itself and second how to pass fu as parameter inv.useFu(impl.fu).
Edit after bipll answer
The suggested usage of inv.useFu() solves the second problem of my question.
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I still need to call fu as a pointer to member function;
The way your useFu is declared now, it should be called as
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I guess that's not what you wanted. It should rather be
template<class F> void useFu(F &&f) { std::invoke(std::forward<F>(f)); }
or simply
void useFu(std::function<void()> f) { std::invoke(std::move(f)); }
and called as
useFu([&]{ impl.fu(); });
(Rather than using a lambda you can bind the method to the object with std::bind in the latter call but almost nobody ever does that.)
I'm currently doing some work with C++/CLI, and am encountering a strange compilation error with the following code:
private ref class LinqHelper abstract sealed
{
public:
generic<typename T, typename U> static Func<T, U>^ Cast()
{
return gcnew Func<T, U>(&LinqHelper::Cast);
}
private:
generic<typename T, typename U> static U Cast(T val)
{
return safe_cast<U>(val);
}
};
error C3352: 'Cast' : the specified function does not match the delegate type 'U (T)'
To be more specific, the problematic line of code is:
return gcnew Func<T, U>(&LinqHelper::Cast);
I find myself at a loss to explain this error. The Cast static member function that I am passing to the Func delegate constructor has the required signature, i.e. U Cast(T val).
Could anyone help shed some light on this for me please?
If it is of any help: i am working with VS 2015 and the C++/CLI project is referencing the .NET framework v4.5.2.
Thank you
The compiler is not happy about having to infer the type arguments for the Cast method. Lousy error message, not uncommon in C++/CLI. Fix:
return gcnew Func<T, U>(&LinqHelper::Cast<T, U>);
I recently started using C++/Cli for wrapping purposes.
Now I'm at a point where I've to know more about the internals.
Consider the following code:
Header file (ignoring .NET namespaces for this example):
public ref class BaseyClass
{
protected:
delegate void TestMethodDelegate(); // TestMethod delegate
BaseyClass(); // constructor
virtual void TestMethod(); // member: method
GCHandle _testMethodHandle; // member: method handle
};
CPP file (ignoring .NET namespaces for this example):
BaseyClass::BaseyClass()
{
_testMethodHandle
= GCHandle::Alloc(
gcnew TestMethodDelegate(this, &BaseyClass::TestMethod));
}
void TestMethod()
{
}
Eventually this class will be used as base class (for a DerivedClass) later and the method "TestMethod()" gets overridden and called from unmanaged code through the delegate pointer.
Now the question: Which method will be referenced by the delegate?
BaseyClass::TestMethod();
or
DerivedClass::TestMethod();
Personally I think the "BaseyClass::TestMethod()" will be referenced by the delegate because even when it's overridden, the delegate points to the (base-)address of BaseyClass. Hence a DerivedClass cannot override the "TestMethod" and use the delegate from BaseyClass.
I just want to be sure. Thanks for your comments and enlightment.
The delegate will be a reference to the derived class's TestMethod. Even though you're passing &BaseyClass::TestMethod, that's a virtual method, you're also passing this, which is the derived type, and both of those are taken into account when the delegate is created.
Other notes:
TestMethodDelegate doesn't need to be inside the class definition. The more standard way is to have the delegate outside of the class, just in the namespace. (Or use the existing built-in one, Action.)
You don't need to GCHandle::Alloc (I assume that's what you meant by Allow). Instead, declare _testMethodHandle as TestMethodDelegate^ (or Action^). In general, you shouldn't need to deal with GCHandle unless you're interfacing with unmanaged code, and this code is all managed.
Here's my test code:
public ref class BaseyClass
{
public:
BaseyClass() { this->_testMethodHandle = gcnew Action(this, &BaseyClass::TestMethod); }
virtual void TestMethod() { Debug::WriteLine("BaseyClass::TestMethod"); }
Action^ _testMethodHandle;
};
public ref class DerivedClass : BaseyClass
{
public:
virtual void TestMethod() override { Debug::WriteLine("DerivedClass::TestMethod"); }
};
int main(array<System::String ^> ^args)
{
BaseyClass^ base = gcnew DerivedClass();
base->_testMethodHandle();
return 0;
}
Output:
DerivedClass::TestMethod
I have been learning D, and am in particular very excited for it's Generic programming capabilities. Delegates are wonderful, and apparently they have completely replaced member-function-pointers, so I was stuck when I wanted to implement something like the following:
template <typename T>
void DispatchMethodForAll(std::vector<T*> & container, void (T::* func)(void))
{
for(typename std::vector<T*>::iterator it = container.begin(); it != container.end(); ++it)
(*it)->*func();
}
According to what I have learned of function pointers and delegates in D, is that neither of them can do this, since function pointers can only be declared for global functions, and delegates have to be bound to an object, there is no "partial delegate" that I can find. As seen here, I cannot use a delegate, since there is no single object that can be bound to the method that is to be called.
I know that I could do it with mixins, and essentially make it a macro. However this really doesn't sound D-like, and I figured there should be "The correct way"
You could still use a delegate here.
void DispatchMethodForAll(T)(T*[] container, void delegate(T*) action)
{
foreach (it; container)
action(it);
}
...
DispatchMethodForAll(container, (Foo* foo) { foo.func(); });
Example: http://www.ideone.com/9HUJa
you can take a page out of the std.algorithm to find out how it does that
void DispatchMethodForAll(alias func, T)(T container)
{
alias unaryFun!func _func
foreach (it; container)
_func(it);
}
btw a delegate can be bound to a struct and the compiler can create a custom struct from local (stack allocated) variables and define a delegate on that
this happens with
void foo(){
int[] array;
int i=0;
void bar(int a){
i+=a;
}
void DispatchMethodForAll(&bar)(array);
writeln(i);//prints the sum of array
}
bar is a delegate bound to a struct with (at least) a member i of type int of which the local variable i is an alias