Representing IUnknown In Managed C++ - c++-cli

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

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.

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

Wrapping void pointer in C++/CLI and C#

I am working on C++/CLI wrapper for C static libary that is eventually used in C# application.
I have function like this in C Library.
long SubscriveEvent(void* handle,device name ,....);
long StartCaptureViceo(handle,...,...);
Here StartCaptureViceo () will use the handle from SubscriveEvent()
I nee to maintain some variable in C# for this void
Now what data type i should use in C++/CLI to Retain.
Please help me for this.
System::IntPtr

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

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);

How to create a global handle in C++-CLI

I am trying to use a C# class in a C++-CLI project, but Visual Studio will only let me declare a handle (^) to a C# object in a local scope, just inside a function. The only way I got it working was declaring a global pointer to a handle:
SUTAdapter::Form1^ *ptForm1;
But if then I create an object inside a function and give its address to the global pointer:
SUTAdapter::Form1^ form1;
form1 = gcnew SUTAdapter::Form1();
ptForm1 = &form1;
(*ptForm1)->incCounter(0);
When the function exits and I try to use the incCounter function inside some other C++-CLI function, the object seems gone (debugger says this == null). Is there a way to have a global handle of a C# code in C++-CLI? I guess global handles are forbidden for some reason I don't understand but I am out of ideas and I need this done. Thank you.
edit:
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception. Why?
This restriction seems consistent with the other CLR-based languages. C# has no concept of a static, function-scoped variable for example. The lack of such functionality in C++/CLI suggests that is the way the CLR works - static objects must be defined at the class scope.
The CLR is object based, so this is just a case of that object-oriented nature influencing the design of languages that run on top of it.
From an OO view point, I like the C# way better anyway.
Ok thanks for your answers but I finally solved it, I found it googling:
http://bytes.com/groups/net-vc/473036-how-define-global-com-object-vc-8-a
It seems that VS doesn't let global handles or static handles inside functions. I am puzzled about this because sometimes it is necessary to access managed objects globally.
The solution is to declare a "GlobalObjects" class with static handles inside it:
ref class GlobalObjects
{
public:
static SUTAdapter::Form1^ hndForm1;
};
This way I can access the C# form/class globally. The error code of the previoous error is C3145, I am still wondering why does not VS allow the declaration of global handles.
Will Visual Studio let you declare a static handle to a C# object in a local scope?
SUTAdapter::Form1^ theForm() {
static SUTAdapter::Form1^ form1 = gcnew SUTAdapter::Form1();
return form1;
}
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception because you are dereferncing a null pointer - it is just like a pointer to any other type in that regard.
I think - and that's without testing it - that the problem you're having is because you're storing a pointer to a local handle, which might confuse the garbage collector a little due to the fact that you're taking a pointer to an automatic object.
Have you tried to replace the above assignment with
*ptForm1 = gcnew SUTAdapter::Form1();
instead of the detour via the local object reference?