I am trying to pass an array of ints from C# to C++/CLI. Here's my code:
// SafeArrayTesting_PlusPlus.cpp
#include "stdafx.h"
#include <comdef.h>
using namespace System;
namespace SafeArrayTesting_PlusPlus
{
public ref class MyCppClass
{
public:
MyCppClass();
~MyCppClass();
void SetMyInts(array<int>^ myInts);
};
MyCppClass::MyCppClass(){}
MyCppClass::~MyCppClass(){}
void MyCppClass::SetMyInts(array<int>^ myInts)
{
// Create safearray
SAFEARRAY *safeArrayPointer;
SAFEARRAYBOUND arrayDim[1]; // one dimensional array
arrayDim[0].lLbound= 0;
arrayDim[0].cElements= myInts->Length;
safeArrayPointer = SafeArrayCreate(VT_UNKNOWN,1,arrayDim);
// copy ints to safearray
for (long lo= 0; lo < myInts->Length; lo++)
{
cli::pin_ptr<int> pinnedIntPointer = &(myInts[lo]);
SafeArrayPutElement(
safeArrayPointer,
&lo,
static_cast<void*> (pinnedIntPointer)); // line XX
}
// do something with the safearray here
}
}
// SafeArrayTesting_Main.cs
using SafeArrayTesting_PlusPlus;
namespace SafeArrayTesting_Main
{
class SafeArrayTesting_Main
{
static void Main()
{
var myCppClass = new MyCppClass();
myCppClass.SetMyInts(new[]{42});
}
}
}
When I run this, line XX throws the following exception:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I have a feeling that I'm doing something basically wrong with the SafeArrayPutElement method. Can you spot the error?
(By the way, I have asked a more complex variation of this question at Passing an array of interfaces from C# to C++/CLI . I think the difference is big enough to warrant two separate questions.)
safeArrayPointer = SafeArrayCreate(VT_UNKNOWN,1,arrayDim);
That creates an array of IUnknown interface pointers. SafeArrayPut() makes sure to increase the reference count of the interface pointer by calling IUnknown::AddRef() since it stores a copy of the pointer in the array.
You can see how that goes kaboom. Create an array of integers instead. Fix:
safeArrayPointer = SafeArrayCreate(VT_I4,1,arrayDim);
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.
Just trying to get a feeler here for what is the best practice for accessing native arrays.
Specifically what I'd like to know is if there is any overhead involved when accessing them via native pointers for arrays of floats or ints.
Am I fine just indexing into my native arrays via pointer arithmetic or should I be copying the entire native block into a managed array and than accessing the managed array?
As it stands I have things setup so that my managed class holds a native pointer. The manage class than retrieves underlying data via the native pointer. This seems reasonable, but I am unsure of what type of interop might be going on behind the scenes.
I appreciate any input.
Snippet Added.
From API:
#define rtArrayItemP(a, pos) (a)->data[(pos) * (a)->width + (a)->element]
My Code:
template<typename T1, typename T2> public ref class ArrayW
{
internal:
ArrayW(T2* arr)
{
_arr = arr;
}
property T2* Array
{
T2* get()
{
return _arr;
}
}
protected:
T1 getarrayelement(int index)
{
return rtArrayItemP(_arr, index);
}
void setarrayelement(int index, T1 value)
{
rtArrayItemP(_arr, index) = value;
}
T2* _arr;
};
I'm new to C++/CLI and I'm wondering what is "best practice" regarding managed type data members. Declaring as handle:
public ref class A {
public:
A() : myList(gcnew List<int>()) {}
private:
List<int>^ myList;
};
or as a value:
public ref class B {
private:
List<int> myList;
};
Can't seem to find definitive advice on this.
When writing managed C++ code, I'm in favor of following the conventions used by the other managed languages. Therefore, I'd go with handles for class-level data members, and only use values (stack semantics) where you'd use a using statement in C#.
If your class member is a value, then replacing the object entirely means that the object would need a copy constructor defined, and not many .NET classes do. Also, if you want to pass the object to another method, you'll need to use the % operator to convert from List<int> to List<int>^. (Not a big deal to type %, but easy to forget, and the compiler error just says it can't convert List<int> to List<int>^.)
//Example of the `%` operator
void CSharpMethodThatDoesSomethingWithAList(List<int>^ list) { }
List<int> valueList;
CSharpMethodThatDoesSomethingWithAList(%valueList);
List<int>^ handleList = gcnew List<int>();
CSharpMethodThatDoesSomethingWithAList(handleList);
It all depends on the lifetime. When you have a private member which lives exactly as long as the owning class, the second form is preferable.
Personally, I would use the second form. I say this because I use frameworks that are written by other teams of people, and they use this form.
I believe this is because it is cleaner, uses less space, and is easier for the non-author to read. I try to keep in mind that the most concise code, while still being readable by someone with minimal knowledge of the project is best.
Also, I have not encountered any problems with the latter example in terms of readability across header files, methods, classes, or data files ...etc
Though I'm FAR from an expert in the matter, that is what I prefer. Makes more sense to me.
class AlgoCompSelector : public TSelector {
public :
AlgoCompSelector( TTree *tree = 0 );
virtual ~AlgoCompSelector(){ /* */ };
virtual void Init(TTree *tree);
virtual void SlaveBegin(TTree *tree);
virtual Bool_t Process(Long64_t entry);
virtual void Terminate();
virtual Int_t Version() const { return 1; }
void setAlgo( Int_t idx, const Char_t *name, TTree* part2, TTree* part3 );
void setPTthres( Float_t val );
void setEthres( Float_t val );
private:
std::string mAlgoName[2]; // use this for the axis labels and/or legend labels.
TTree *mPart1;
TTree *mPart2[2], *mPart3[2]; // pointers to TTrees of the various parts
TBranch *mPhotonBranch[2]; // Used branches
TClonesArray *mPhotonArray[2]; // To point to the array in the tree
for example
I have a method in my native dll, that I want to use. The method returns an object of a type that is also in my native dll.I am trying to write a c++/CLI wrapper.
Now,
Can I get a return value as the object using C++/CLI and how do I do that?
Can we store and pass the native C++ object?
Should I need to create my own class resembling the native C++ class?
How would I marshal a class?
For Example,My native dll has these classes,
class X
{
/* some props and methods. */
};
Class Y
{
X* someMethod();
};
I need to wrap the someMethod class using C++/CLI. Will I be able to get the return value in the CLI?
Returning pointers to C++ objects from an exported function in a DLL is a pretty bad idea. It is a nasty memory management problem, you'd expect the client code to release the object. That can only come to a good end when both DLLs use the exact same version of the DLL version of the CRT (/MD compile option). If you can't recompile the native DLL then stop right now, you cannot make it work reliably or you'll have a big maintenance problem in the future.
Anyhoo, you need a wrapper for both classes. They should resemble this:
#pragma managed(push, off)
#include "xandy.h"
#pragma managed(pop)
using namespace System;
namespace something {
public ref class XWrapper {
X* mX;
public:
XWrapper(X* obj) : mX(obj) {}
~XWrapper() { this->!XWrapper(); }
!XWrapper() {
// Trouble is here!!!
delete mX;
}
};
public ref class YWrapper {
Y* mY;
public:
YWrapper() { mY = new Y; }
~YWrapper() { this->!YWrapper(); }
!YWrapper() { delete mY; }
XWrapper^ someMethod() {
return gcnew XWrapper(mY->someMethod());
}
};
}
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.