This is a similar question to this SO post, which I have been unable to use to solve my problem. I have included some code here, which will hopefully help someone to bring home the message that the other posting was getting at.
I want to write a CLI/C++ method that can take a void pointer as a parameter and return the managed object (whose type I know) that it points to. I have a managed struct:
public ref struct ManagedStruct { double a; double b;};
The method I am trying to write, which takes a void pointer to the managed struct as a parameter and returns the struct.
ManagedStruct^ VoidPointerToObject(void* data)
{
Object^ result = Marshal::PtrToStructure(IntPtr(data), Object::typeid);
return (ManagedStruct^)result;
}
The method is called here:
int main(array<System::String ^> ^args)
{
// The instance of the managed type is created:
ManagedStruct^ myData = gcnew ManagedStruct();
myData->a = 1; myData->b = 2;
// Suppose there was a void pointer that pointed to this managed struct
void* voidPtr = &myData;
//A method to return the original struct from the void pointer
Object^ result = VoidPointerToObject(voidPtr);
return 0;
}
It crashes in the VoidPointerToObject method on calling PtrToStructure , with the error: The specified structure must be blittable or have layout information
I know this is an odd thing to do, but it is a situation I have encountered a few times, especially when unmanaged code makes a callback to managed code and passes a void* as a parameter.
(original explanation below)
If you need to pass a managed handle as a void* through native code, you should use
void* voidPtr = GCHandle::ToIntPtr(GCHandle::Alloc(o)).ToPointer();
// ...
GCHandle h = GCHandle::FromIntPtr(IntPtr(voidPtr));
Object^ result = h.Target;
h.Free();
(or use the C++/CLI helper class gcroot)
Marshal::PtrToStructure works on value types.
In C++/CLI, that means value class or value struct. You are using ref struct, which is a reference type despite use of the keyword struct.
A related problem:
void* voidPtr = &myData;
doesn't point to the object, it points to the handle.
In order to create a native pointer to data on the managed heap, you need to use pinning. For this reason, conversion between void* and Object^ isn't as useful as first glance suggests.
Related
I dont understand why initialization of dynamically allocated structure needs to be done like this (using shared ptr)
Just to notify that I am using C++11
If we have struct like this
struct Meme {
std::string s;
Meme* p;
}
and later in code, I need to dynamically allocated memory for this structure using shared_ptr, but I need to do instant initialization of structure.
Why it is done like this?
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
part that confuses me is this one :
std::make_shared<Meme>(Meme{imena.at(i),nullptr});
If we set that shared_ptr points to struct Meme, why we need to specify again that initialization list is for struct Meme, by saying
(Meme{imena.at(i),nullptr})
Why this would not work:
std::shared_ptr<Meme> novi=std::make_shared<Meme>({imena.at(i),nullptr});
Is this maybe that initialization list cannot deduct that it should like convert to struct Meme because there is no direct usage of struct Meme(even though make_shared points to struct Meme) ?
make_shared forwards arguments to constructor.
Make shared_ptr
Allocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it (with a use count of 1).
This calls the copy constructor of Meme from new instance you create with Meme{imena.at(i),nullptr}.
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
The correct way to construct it with make_shared from forwarded arguments is to create constructor in struct:
struct Meme {
std::string s;
Meme* p;
Meme(const std::string& s, Meme* p) : s(s), p(p) {}
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>(imena.at(i),nullptr);
Also you can create an instance with (default) empty constructor and then set its members:
struct Meme {
std::string s;
Meme* p = nullptr;
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>;
novi->s = imena.at(i);
I've got the following struct:
struct Param
{
double** K_RP;
};
And I wanna perform the following operations on "K_RP" in CUDA
__global__ void Test( struct Param prop)
{
int ix = threadIdx.x;
int iy = threadIdx.y;
prop.K_RP[ix][iy]=2.0;
}
If "prop" has the following form, how should I do my "cudaMalloc" and "cudaMemcpy" operations?
int main( )
{
Param prop;
Param cuda_prop;
prop.K_RP=alloc2D(Imax,Jmax);
//cudaMalloc cuda_prop ?
//cudaMemcpyH2D prop to cuda_prop ?
Test<<< (1,1), (Imax,Jmax)>>> ( cuda_prop);
//cudaMemcpyD2H cuda_prop to prop ?
return (0);
}
Questions like this get asked from time to time. If you search on the cuda tag, you'll find a variety of examples with answers. Here's one example.
In general, dynamically allocated data contained within structures or other objects requires special handling. This question/answer explains why and how to do it for the single pointer (*) case.
Handling double pointers (**) is difficult enough that most people would recommend "flattening" the storage so that it can be handled by reference with a single pointer (*). If you really want to see how the double pointer (**) method works, review this question/answer. It's not trivial.
I dont know a lot about C++, but I have to make work some C++ code with .NET. I try with DLLImport but I failed. So I try with C++/CLI to make kind of a wrapper.
But I'm not sure to understand everything...
This is the basic C++ H file with the function I want to export (MyFunction)
extern "C"
{
__declspec(dllexport) IplImage* MyFunction(IplImage *src, std::string* name, OneEnumerationType myEnum, bool myBool, float myFloat);
}
This is the Wrapper h code.
#include "MyFunction.h"; // the file containing the h code
#include <string>
namespace MyWrapper{
public ref class MyWrapperClass {
public:
MyWrapper(){};
IplImage^ GetMyFunction(IplImage *src, std::string^ name, OneEnumerationType myEnum, bool myBool, float myFloat);
}
This is the Wrapper cpp code.
#include "MyWrapperCode.h";
namespace MyWrapper{
IplImage^ MyWrapperClass::GetMyFunction(IplImage* src, std:string^ name, OneEnumerationType myEnum, bool myBool, float myFloat){
MyFunction(src, name, myEnum, myBool, myFloat);
}
}
These are my questions :
1) When I'm compiling, the error is "'^ : cannot use this indirection on type IplImage' and same message for type "std::string".
I have followed this logical :
ClasseNative clNat2 = *clNat; --> ClasseManagee clMan2 = *clMan;
ClasseNative &clNat3 = clNat2; --> ClasseManagee %clMan3 = clMan2;
ClasseNative *clNat4 = &clNat2; --> ClasseManagee ^clMan4 = %clMan2;
I have seen, that It was better to use System::String. I try this way but the initial function is using std::string... BTW, why is it better to change ?
2) How do I get the MyFunction IplImage result ? Thru a private member and a get I suppose but I dont know how to initialize it...
3) Tricky question. Is it possible for me to put the CLI obtains IplImage structure (from the OpenCV library) (the result of my function) inside a IplImage .NET structure, when I ll called my wrapper ? Dont know if the question is understandable...
Thanks a lot for your help.
Turning around for 3 days on this problem...
Your wrapper class needs to create a new std::string based on the content of a System::String^ parameter then pass to your native function. Otherwise you need to rewrite the function to take something else as the string input, for example a LPWSTR or LPCSTR.
You can write a ref class to have properties for all data that an IplImage would have, then pass that to your wrapper class. Your wrapper class then create an IplImage object based on the data of the ref class and pass to the native function. Reverse the data copying direction for the return value.
1) just by adding ^ you cannot change a native object to become managed, you have to create wrappers or transfer the data for example:
std::string nativeString = "my string";
String^ managedString = gcnew String(nativeString.c_str());
//now you can return it as
2) create a managed wrapper or use primitive datatype to transfer the data
3) note sure if this will help but look at Emgu.CV
try reading abit more about C++\CLI here are a few nice tutorials:
Quick C++/CLI - Learn C++/CLI in less than 10 minutes
C++/CLI for the C# programmer
I am having a compiler issue in Visual Studio 2005 using the standard C compiler when trying to do a structure copy from one location to another.
The types are defined in a file as follows:
definition.h
#define MAX 7
typedef struct{
char recordtext[18];
boolean recordvalid;
}recordtype;
typdef recordtype tabletype[MAX];
typedef struct{
tabletype table;
}global_s;
Let us pretend that a global_s "object" is instantiated and initialized somewhere and a pointer to this structure is created.
#include "definition.h"
global_s global;
global_s* pglobal = &global;
init(&pglobal);
Meanwhile, in another file (and this is where my problem is) i am trying to create a local tabletype object, and fill it with the global table member, using a get method to protect the global (lets pretend it is "static")
#include "definition.h"
extern global_s* pglobal;
tabletype t;
gettable(&t);
void gettabl (tabletype* pt)
{
*pt = pglobal->table;
}
When I go to compile, the line in the gettable function throws a compiler error "error C2106: '=': left operand must be l-value. It looks as though this should behave as a normal copy operation, and in fact if I perform a similar operation on a more basic structure I do not get the error. For example If I copy a structure only containing two integers.
Does anyone have a solid explanation as to why this operation seems to be incorrect?
(Disclaimer: I have developed this code as a scrubbed version of my actual code for example purposes so it may not be 100% correct syntactically, I will edit the question if anyone points out an issue or something needs to be clarified.)
It's the arrays in the struct; they cannot be assigned. You should define an operator=() for each of the structs, and use memcpy on the arrays, or copy them in a loop element by element.
(IF you want to get a reference to your global variable):
I am not sure, if this is correct (and the problem), but I think besides function prototypes, arrays and pointers (to arrays 1. element) are NOT exactly the same thing. And there is a difference between pointer to array and pointer to the 1. element of an array)
Maybe taking the adress of the array:
*pt = &(pglobal->table);
Anyway it might be better not to fetch the address of the whole array but the address of the first element, so that the resulting pointer can be used directly as record array (without dereferencing it)
recordtype* gettable (size_t* puLength)
{
*puLength = MAX;
return &(pglobal->table[0]);
}
(IF you want a copy of the table):
Arrays can't be copied inplace in C90, and of course you have to provide target memory. You would then define a function get table like this:
void gettable (recordtype * const targetArr)
{
size_t i = 0;
for (; i < MAX; i++) targetArr[i] = pglobal->table[i];
return;
}
an fully equivalent function prototype for gettable is:
void gettable(recordtype[] targetArr);
Arrays are provided by refernce as pointer to the first element, when it comes to function parameters. You could again ask for an pointer to the whole array, and dereference it inside gettable. But you always have to copy elementwise.
You can use memcopy to do the job as 1-liner. Modern compilers should generate equally efficent code AFAIK.
I do some thin wrapper of some scientific library (http://root.cern.ch) from unmanaged to managed world using C++ cli.
Reading of the special file format (which is the main goal) is implemented through:
1) Once a lifetime call of SetBranchAddress(const char name, void* outputVariable) to let it know an address of your variable
2) Than you N time call GetEntry(ulong numberOfRow) wthich fills this void* outputVariable with the appropriate value;
I put this example of usage :
double myValue; //this field will be filled
//We bind myValue to the 'column' called "x" stored in the file"
TTree->SetBranchAddress("x", &myValue);
// read first "entry" (or "row") of the file
TTree->GetEntry(0);
// from that moment myValue is filled with value of column "x" of the first row
cout<<"First entry x = "<<myValue<<endl;
TTree->GetEntry(100); //So myValue is filled with "x" of 101 row
...
So in C++/CLI code the problem is with binding managed elementary types to this void * pointer;
I have tried 3 approaches:
namespace CppLogicLibrary {
public ref class SharpToRoot
{
double mEventX;
double *mEventY;
IntPtr memEventZ;
///Constructor
SharpToRoot()
{
mEventy = new double();
memEventZ= Marshal::AllocHGlobal(sizeof(double));
}
void SetBranchAddresses()
{
pin_ptr<double> pinnedEventX = &mEventX;
mTree->SetBranchAddress("ev_x", pinnedEventX);
mTree->SetBranchAddress("ev_y", mEventY);
mTree->SetBranchAddress("ev_z", memEventZ.ToPointer());
...
//now I read some entry to test... just in place
mTree->GetEntry(100);
mTree->GetEntry(101);
double x = mEventX;
double y = *mEventY
double z = (double)Marshal::PtrToStructure(memEventZ, Double::typeid);
}
...
All of 3 variants are compiled with no errors, goes with no exceptions... BUT fills its (void *) values with some rubbish value like 5,12331E-305. In unmanaged code all works fine.
What could be the error with such void* to C++/CLI elementary types binding?
The problem was that internally data was presented by floats inside of this library. So, when it was mapped and processed as doubles on the C# side, it gave 5,12331E-305.
Each of this 3 variats worked. And, from my point of view, using of
pin_ptr pinnedEventX = &mEventX;
was improper in this case, because it doesn't persist between functions execution;
What I'm not sure, why this "float" situation was handled in native C++. As I wrote before, there wasn't any problem.