How to convert from C# ref type to CLI\C++ ^% type - c++-cli

I am writing an application in Managed C++ (CLI\C++). In which I am using a library (.dll file) which is written in C#.
In a file I am encountering a problem.
I am implementing functions of an interface which is written in the library.
The declaration of a function in the library is as given below:
COMWORKSPACELib.IWorkspaceEvents.WorkspaceMessage(int, string, COMWORKSPACELib.EnumNotificationCode, COMWORKSPACELib.EnumNotificationType, string, ref COMWORKSPACELib.EnumNotificationReply);
When I write the same code in CLI\C++ the declaration is like:
WorkspaceMessage(int workspaceToken, String ^description, EnumNotificationCode ^code, EnumNotificationType ^type, String ^source, EnumNotificationReply ^%action);
Here, the compiler is giving me error that the “class must provide an implementation for the interface method”. Because the parameters passed in both function declarations are syntactically different.
Is there any alternative way to match the library declaration?
If I remove the “^’ & ‘%’ to match the library declaration then it gives further errors in the code.

Are EnumNotifcationCode, EnumNotificationType, and EnumNotficationReply all enums? That is, are they value types? If so, then it should be declared as follows:
WorkspaceMessage(int workspaceToken,
String^ description,
EnumNotificationCode code,
EnumNotificationType type,
String^ source,
EnumNotificationReply% action);

Related

Ambiguous because multiple kinds of members with this name exist in interface

this is the Interface:
Namespace IBasBS100
Public Interface IBasBSMoedas <DispId(0)> <Obsolete("This method is obsolete. Use Actualiza(BasBE100.BasBEMoeda objMoeda, ref string strAvisos) instead.", False)>
Sub Actualiza(objMoeda As BasBEMoeda, Optional strAvisos As String = "")
<DispId(18)>
Sub Actualiza(objMoeda As BasBEMoeda, ByRef strAvisos As String)
<DispId(2)>
when i try to call the function that is not depracated it gives me the ambiguous error message:
Dim avisos As String
Dim bsmoedas As IBasBSMoedas = MotorPRI.Base.Moedas
bsmoedas.Actualiza(m, avisos)
I think its calling the depracated method.
Is there any way that i could explicitly call the non depracated method "Actualiza(objMoeda As BasBEMoeda, ByRef strAvisos As String)"?
PS: I can not change the interface, it's an external Library
I can only assume that the interface code was written in C# because that VB code won't compile. In VB, you don't explicitly state when passing an argument by reference, so the there's no way to differentiate between those two methods when calling one in VB code. In C#, you specify the ref or out keyword when passing an argument by reference, so there is no ambiguity in which overload you are calling, so it's allowed.
In short, you cannot call that interface method in VB. You can implement the interface in a class in VB and use a different name for one of the methods but you'd still have to call it through the class, not the interface. If you want to be able to use that interface then you're going to have to do it in C# code. Perhaps write a library in C# for the code that uses that interface and then consume that in your VB app.
I guess the other alternative to do it in VB would be to do so via Reflection. Far from ideal but I don't see another way.
Primavera v10 funtions and VisualBasic aren't compatible with each other. Some may work, most won't. I would recommend changing to C# since this is the "supported" language of primavera.

Which is the correct form for a C++-CLI copy constructor?

I have some code like this:
MyClass::MyClass(MyClass^ objToCopyFrom);
Which is producing an error:
'type' : ref class does not have a user-defined copy constructor
When I look up the error, it suggests my code should look like this:
MyClass::MyClass(MyClass% objToCopyFrom);
My question is therefore, which version is correct or are they both correct?
Only your second version is correct:
MyClass::MyClass(MyClass% objToCopyFrom);
or its variant:
MyClass::MyClass(const MyClass% objToCopyFrom);
MyClass% is a so-called Tracking Reference which is the conceptual equivalence of a reference in native C++, only for CLR types.
While copy constructors in native C++ can have a number of different signatures, what they all have in common is that the other object that's being copied is passed in as a reference. C++/CLI stays close to that principle, but uses its own type of object references, a tracking reference.

CLI/C++ function overload

I am currently writing a wrapper for a native C++ class in CLI/C++. I am on a little GamePacket class at the moment. Consider the following class:
public ref class GamePacket
{
public:
GamePacket();
~GamePacket();
generic<typename T>
where T : System::ValueType
void Write(T value)
{
this->bw->Write(value);
}
};
I want that I'm able to call the function as following in C#, using my Wrapper:
Packet.Write<Int32>(1234);
Packet.Write<byte>(1);
However, I can't compile my wrapper. Error:
Error 1 error C2664: 'void System::IO::BinaryWriter::Write(System::String ^)' : cannot convert argument 1 from 'T' to 'bool'
I don't understand this error, where does the System::String^ comes from. I'm seeing a lot of overloads of the Write() method, does CLI/C++ not call the correct one, and if so, how can I make it call the correct one?
Reference MSDN: http://msdn.microsoft.com/en-us/library/system.io.binarywriter.write(v=vs.110).aspx
Templates and generics don't work the same.
With templates, the code gets recompiled for each set of parameters, and the results can be pretty different (different local variable types, different function overloads selected). Specialization makes this really powerful.
With generics, the code only gets compiled once, and the overload resolution is done without actually knowing the final parameters. So when you call Write(value), the only things the compiler knows is that
value can be converted to Object^, because everything can
value derives from ValueType, because your constraint tells it
Unfortunately, using just that information, the compiler can't find an overload of Write that can be used.
It seems like you expected it to use Write(bool) when T is bool, Write(int) when T is int, and so on. Templates would work like that. Generics don't.
Your options are:
a dozen different copies of your method, each of which has a fixed argument type that can be used to select the right overload of BinaryWrite::Write
find the overload yourself using reflection, make a delegate matching the right overload, and call it
use expression trees or the dynamic language runtime to find and make a delegate matching the right overload, and then you call it

C++/CLI optional arguments

Why i cannot declare default arguments for member functions of a managed type or generic functions? C# 4.0 introduced Named and Optional Arguments; there is a similar thing for CLI?
I do not understand why is not possible to declare a method like this:
void Optional(int argument = 0);
And then when I call Optional(); the compiler does not translate this call into: Optional(0);.
It looks like the C++/CLI Compiler doesn't emit the correct IL directive for that. It doesn't emit the directive .param [1] = int32(0), which C# uses for recognizing default parameters. If you open the generated assembly in ILDasm, you'll see it.
A way that compiles would be to use the attributes Optional and DefaultParameterValue from the System::Runtime::InteropServices namespace, but C# doesn't use those for default parameters, so currently there's no easy way around creating an overload.
You can find the question asking about those Attributes here: https://stackoverflow.com/a/4974528/93652

Representing IUnknown In Managed C++

I building Wrapper in C++/CLI for C Static library to be used in .NET application through C#
I have function like this in C
long My_COM_Interface( PVOID hDevice,IUnknown **pUnknown);
How to declare IUnknown ** in C++/CLI
for first argument I am using IntPtr but Not able to find out the Replacement for IUknown.
I have another COM Data type GUID in another function this is also an issue for me.
Please Help me find the relacement for data type IUnknown and GUID.
There is no replacement.
C++/CLI understands native types just fine. Include the right header files, and you can use IUnknown* like always.
I'd refer to the APIs, e.g.
public static IntPtr GetIUnknownForObject(Object o);
This API can simply be used from C++/CLR and suggests you should use IntPtr^
try using parameter like;
ref object pUnknown
and use it like
MyObject o = pUnknown as MyObject