|
-
August 11th, 2010, 02:35 PM
#1
Pinning an array
I am having problems pinning an array to pass to a Native function as a reference.
here is the native code:
Code:
typedef HANDLE HDIB
int LoadArrayFromFilename(HDIB ahdib[], int nMax, const char* pszFile);
Now here is my managed to unmanaged bridge function:
Code:
int Toolkit::Dib::LoadArrayFromFilename(array<IntPtr>^% ahdib, int nMax, String^ pzFileName)
{
pin_ptr<IntPtr> p = &ahdib[0];
HDIB * native = (HDIB*)p->ToPointer();
return ::DIB_LoadArrayFromFilename(native, nMax, (char*)SystemStringToCSTR(pzFileName));
}
once inside the native DIB_LoadArrayFromFilename, the pointer 'native' is null, and the clr throws an AccessViolationException ("Trying to read or write protected memory").
Here is example VB code passing an array to be filled out:
Code:
Dim pages(100) As IntPtr
Toolkit.Dib.LoadArrayFromFilename(pages, 100, szFileName)
So, does anyone know what is wrong with my managed bridge function?
-
August 12th, 2010, 12:20 AM
#2
Re: Pinning an array
I see here two strange points, though I am not sure that this is the reason on the failure:
1) array<IntPtr>^%
% is not necessary in this case, since you don't change the reference in this function.
2) array<IntPtr> in mapped to the HANDLE array. Are you sure that IntPtr structure has the same size as HANDLE? Possibly it is, but this is dangerous. pin_ptr should be applied only to simple types like integer.
If performance is not critical, create int array (long for x64), copy every IntPtr to it in the managed code, and then call DIB_LoadArrayFromFilename with pinned int array.
-
August 12th, 2010, 01:21 AM
#3
Re: Pinning an array
hi,
performance is not critical, create int array (long for x64), copy every IntPtr to it in the managed code, and then call DIB_LoadArrayFromFilename with pinned int array.
regards,
phe9oxis,
http://www.guidebuddha.com
-
August 12th, 2010, 08:50 AM
#4
Re: Pinning an array
Thanks guys this helps but I need to investigate further. I might not have been specific enough, ahdib is an array getting passed to DIB_LoadArrayFromFilename where pages from a file are getting loaded into the array. when all is said and done the ahdib parameter needs to get returned, hence the tracking reference. Maybe you are telling me I dont need to because I am pinning it? I would have posted the definition for the native function but I am not sure I am allowed to.
When I was using P/Invoke IntPtr mapped to handle when declaring functions in the client. I can assume the clr does some implicit conversion with IntPtr when using P/Invoke. Intellisense tells me IntPtr is "a platform-specific type that is used to represent a pointer or a handle".
I can say, in the native function the access violation occurs here:
Code:
// parameter: HDIB ahdib[]
memset(ahdib, 0, count*sizeof ahdib[0]); // throws the AccessViolationException
before the above code is executed, in visual studio's debugger it shows ahdib is 0x00000000 hes the access violation
-
August 12th, 2010, 08:59 AM
#5
Re: Pinning an array
You don't need % because array itself is passed by reference. % means that array reference is passed by reference. For example, in C++ you can pass array as char*:
Code:
void SomeDunction(char* ptr)
{
p[0] = 0; // this change is visible to caller
}
% is like: char** ptr - not necessary in this case, unless you want to change ptr itself.
However, this is not critical. But I would not used pinned array for anything except simple types like int.
-
August 12th, 2010, 09:44 AM
#6
Re: Pinning an array
Despite type issues, I dont believe the memory is even getting to the native code.
in general terms, how does one convert a c++/cli array to c++ pointer to be passed to a native function.
I am sorry if you all are getting frustrated with me. There is very little documentation out there, so I appretiate this.
-
August 12th, 2010, 10:24 AM
#7
Re: Pinning an array
Basically, In a native C++ environment I would call the function like this:
Code:
HANDLE arrOfDibs[100];
int numPagesLoaded = DIB_LoadArrayFromFilename(arrOfDibs, 100, "foo.tif");
if (numPagesLoaded > 4)
{
DIB_RandomProcessingFunc(arrOfDibs[3]);
}
for (int i = 0; i < numPagesLoaded; i++)
{
DIB_Free(arrOfDibs[i]); // Each Dib is created with windows GlobalAlloc function, so it needs to be freed
}
I have wrapped the other DIB_*** functions all fine and dandy, but I am having a hard time wrapping DIB_LoadArrayFromFilename! I cant seem to get the array of handles assigned to an (VB.Net or C#) array of IntPtr, which is how I was representing them when using P/Invoke.
-
August 12th, 2010, 11:29 AM
#8
Re: Pinning an array
This might be resolved, heres what I did:
Code:
int Toolkit::Dib::LoadArrayFromFilename(array<IntPtr>^ ahdib, int nMax, System::String^ pzFileName)
{
const int size = ahdib->Length;
HDIB * arr = new HDIB[size];
int num = ::DIB_LoadArrayFromFilename( arr, nMax, (char*)SystemStringToCSTR(pzFileName));
Marshal::Copy(IntPtr(static_cast<void*>(arr)), ahdib, 0, size);
delete arr;
return num;
}
to bypass the pin_ptr issue i allocate memory on the native heap, then copy the data to my managed array. I suppose this method is a bit slower but not enough to make a difference.
If anyone sees anything wrong with the above code I appretiate the input.
otherwise, thanks everyone who replied!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|