The unmanaged function(pure c++, if that matters):
void fooC(float& result);
I define the wrapper as (managed wrapper, c++\cli):
void foo(float% result) //managed interface, need to pass result back to caller
{
fooC(???);//how to call unmanaged function?
}
how to pass reference parameter in the wrapper?
You can't convert a tracking reference to an unmanaged reference or pointer. The garbage collector would cause havoc when the passed float is a field in an object. You'll need to use a temporary:
void foo(float% result) {
float temp;
fooC(temp);
result = temp;
}
Related
For example I'm having a class with three overloaded methods like this:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
// Method implementation.
}
}
My question is when I call the sum method of MyClass by passing any value (integer, string or object) it should invoke only third method (with object type input parameter)
class MainClass
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
obj.sum(10);
obj.sum("X")
}
}
You said "without type casting" but you can't, because you need some way to indicate to the compiler which version to call, and the runtime uses the type it sees to do that bit. Boxing the int as an object means the compiler will pick the object version
sum(1);//call int version
sum((object)1); //call object version
sum((string)(object)"1"); //call string version
sum((object)(int)(object)1); //call object version
First of all, let me say that if you sometimes want to call one version of the sum function when working with ints and sometimes want to call another, overloading probably isn't the right tool to use. Overloading works best when you are implementing conceptually the same operation for a number of different types, and you want the compiler to figure out automatically which function is the right one to call for each type; if you need more manual control over which function is called, you're probably better off using different names.
That said, if you're sure that this is what you want to do, you could implement the overloaded version for object in terms of another function in the public interface, as in:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
sum_object(o);
}
int sum_object(object o)
{
// Method implementation for objects
}
}
Then, when you want to apply the object version to int and string objects, you just call sum_object directly instead.
I have created a new managed, reference class in C++ cli. And now I want to overload equality of objects of this class.
public ref class DerivedFromObject {
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (const DerivedFromObject%, const DerivedFromObject%);
static bool operator== (const DerivedFromObject%, const DerivedFromObject%);
}
As far as I know from C#, operator!= calls operator==, that calls Equals, which refers to GetHashCode.
bool DerivedFromObject::operator==(const DerivedFromObject % a, const DerivedFromObject % b)
{
a.Equals((Object^)%b); // Error
}
In the snippet above, Equals and GetHashCode cannot be called on a const object, that's why I cannot call Equals from operator==.
How can I mark method that doesn't change the object in C++ cli? Or What the most appropriative way to define equality chain?
There's two things here:
.Net doesn't really have the concept of const in the way that C++ does. C++/CLI will enforce the rules that C++ has, but since .Net doesn't use it, no library methods are declared const, so you'll have problems calling just about any method. Rather than being explicitly declared like in C++, it's just by convention that methods like equals don't modify their parameters.
Since you used const%, I think you were trying to parallel the C++ convention of passing const& parameters. % is more similar in usage to ** double pointer than to &: You pass things parameters as % (or ^% for reference types) when the method can assign a value to the parameter, and it should be available to the calling method.
Here's how I would implement this:
public ref class DerivedFromObject : IEquatable<DerivedFromObject> {
virtual bool Equals(DerivedFromObject^ other);
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (DerivedFromObject^, DerivedFromObject^);
static bool operator== (DerivedFromObject^, DerivedFromObject^);
}
One other thing you said:
...Equals, which refers to GetHashCode.
Be careful here, because it is possible for unequal objects to have the same hash code.
GetHashCode will need to evaluate everything, and then if the hash codes are equal, then Equals need to evaluate everything again to be sure they're actually equal. It'll probably be more efficient to not look at the hash code, just compare the objects field by field, and bail out as soon as they're not equal.
I'm writing a C++/CLI extension, and am having issues getting the typing to work out. I'd appreciate your help and hope that I'm making a simple mistake with casting or passing parameters.
Firstly, here is the definition of the unmanaged function I'm trying to call (and which I can't change):
int getResponse(const RequestObject& requestObj, ResponseObject& responseObj);
Second, my unmanaged C++ RequestObject has a definition like so (which I also can't change):
class RequestObject
{
public:
RequestObject();
void addElement(int value, int age);
}
Now, in my managed C++/CLI code (using the 'IJW' interop ability), I want to call into this function. You'll note that I have unmanagedClassInstance (which holds the method given by the above getResponse function definition), and ManagedRequestObject reqs (which is just the managed version of what I want to put into the RequestObject).
RequestObject* unRequest = new RequestObject();
// Here I'm taking things from a managed version of RequestObject and making
// the unmanaged instances:
for each (ManagedRequestObject^ req in reqs) {
unRequest->addElement(marshal_as<int>(req->getValue()),
marshal_as<int>(req->getAge()));
}
// Call into the unmanaged object to get the request processed:
ResponseObject* unResponse = new ResponseObject();
int result = unmanagedClassInstance->getResponse(unRequest, unResponse);
Can you please help me understand how to correctly pass unRequest and unResponse into the getResponse() function?
If you keep using pointers for your unmanaged objects (which you might want to reconsiderate), you should be able to call the unmanaged function like this:
int result = unmanagedClassInstance->getResponse(*unRequest, *unResponse);
But unless strictly necessary, I'd suggest you do this instead:
RequestObject unRequest;
// Here I'm taking things from a managed version of RequestObject and making
// the unmanaged instances:
for each (ManagedRequestObject^ req in reqs) {
unRequest.addElement(marshal_as<int>(req->getValue()),
marshal_as<int>(req->getAge()));
}
// Call into the unmanaged object to get the request processed:
ResponseObject unResponse;
int result = unmanagedClassInstance->getResponse(unRequest, unResponse);
What does gcroot mean? I found it in code I am reading.
gcroot is a C++/cli template class that eases holding managed types in C++/cli classes.
You can for example have the following:
#include <msclr/gcroot.h>
using namespace msclr;
class Native {
public:
Native(Object ^obj) :
netstring(obj->ToString()) { // Initializing the gcroot<String ^>
}
~Native() {
}
void Print() {
array<Char> ^chars = netstring->GetChars(); // Dereferencing the gcroot<String ^>
_wprintf("netstring is:");
if (chars->Length > 0) {
pin_ptr<Char> charptr = &(chars[0]);
_wprintf("%s", (wchar_t const *)charptr);
}
}
private:
gcroot<String ^> netstring;
};
gcroot acts as a reference to the managed object or value type instance and is doing all the work when copying the object or value type instance.
Normally you need to work with GCHandle and some C functions of the .NET framework. This is all encapsulated in gcroot.
When the .NET garbage collector runs, it determines which objects are still in use by doing reachability analysis. Only the managed heap is analyzed while looking for pointers to objects, so if you have a pointer from a native object to a managed object, you need to let the garbage collector know, so it can include it in reachability analysis, and so it can update the pointer if the target moves during compaction.
As rstevens said, the .NET GCHandle class does this, and C++/CLI is a C++-oriented wrapper for GCHandle which adds type safety and convenient syntax.
Suppose I write the following code:
public ref class Data
{
public:
Data()
{
}
Int32 Age;
Int32 year;
};
public void Test()
{
int age = 30;
Int32 year = 2010;
int* pAge = &age;
int* pYear = &year;
Data^ data = gcnew Data();
int* pDataYear = &data->Year; // pData is interior pointer and the compiler will throw error
}
If you compile the program, the compiler will throw error:
error C2440: 'initializing' : cannot convert from 'cli::interior_ptr' to 'int *'
So I learned the "&data->Year" is a type of interior pointer.
UPDATES: I tried to use "&(data->Year)", same error.
But how about pAge and pYear?
Are they native pointers, interior pointers or pinned pointers??
If I want to use them in the following native function:
void ChangeNumber(int* pNum);
Will it be safe to pass either pAge or pYear?
They (pAge and pYear) are native pointers, and passing them to a native function is safe. Stack variables (locals with automatic storage lifetime) are not subject to being rearranged by the garbage collector, so pinning is not necessary.
Copying managed data to the stack, then passing it to native functions, solves the gc-moving-managed-data-around problem in many cases (of course, don't use it in conjunction with callbacks that expect the original variable to be updated before your wrapper has a chance to copy the value back).
To get a native pointer to managed data, you have to use a pinning pointer. This can be slower than the method of copying the value to the stack, so use it for large values or when you really need the function to operate directly on the same variable (e.g. the variable is used in callbacks or multi-threading).
Something like:
pin_ptr<int> p = &mgd_obj.field;
See also the MSDN documentation