PInvoking byte[] to C++ returns first byte
-
Saturday, April 28, 2012 11:31 PM
Please dont link me to another thread I cant find any that help, if you cant correct my code for me dont bother posting i'm fed up of my posts going wildly off topic...
__declspec(dllexport) bool BlankEqualPixels(char* a, char* b, int size){ for(unsigned int i=0; i<size; i+=4) { if(a[i]==b[i]&&a[i+1]==b[i+1]&&a[i+2]==b[i+2]){ a[i]=a[i+1]=a[i+2]=a[i+3]=0; } } return true; }
I'm getting very frustrated with this stupid bloody C++ I just need this in C++ because C# is far too slow- Edited by I installed vista on my bin Saturday, April 28, 2012 11:31 PM
All Replies
-
Sunday, April 29, 2012 4:21 AM
It can be frustrating and responders should try toif you cant correct my code for me dont bother posting i'm fed up of my posts going wildly off topic...
avoid doing that. But these are public forums, and
the starter of a thread doesn't "own" it. So anyone
is free to respond if they feel they can make a
contribution - even if the OP doesn't see it that
way. You have to learn to live with it, or post
in a strictly moderated forum.
Speaking of Netiquette -
This thread duplicates material from another thread:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/f352394e-e850-489e-9724-3960ca38a6e0
Multi-posting is actively discouraged in these forums,
as it can waste time and bandwidth when people post
answers which have already been posted elsewhere in
another thread. Don't be surprised if these two
threads get merged by a moderator.
- Wayne
- Proposed As Answer by Helen ZhaoModerator Monday, May 07, 2012 2:08 AM
-
Sunday, April 29, 2012 5:21 AM
Hello "I installed vista on my bin",
1. My interpretation of the question is as follows :
1.1 BlankEqualPixels() is an exported function that you want to call in C# to perform some processing work.
1.2 You want the C# code to call BlankEqualPixels() passing 2 (equal-lengthed) managed byte arrays as parameters with the length of the arrays passed as the 3rd parameter.
1.3 When the BlankEqualPixels() function returns, you want the changes done to the arrays (inside BlankEqualPixels()) to be permanently reflected in the C# client code.
2. If the above descriptions are correct, then you could declare the BlankEqualPixels() function as follows on C# :
[DllImport("helperdll.dll", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool BlankEqualPixels([MarshalAs(UnmanagedType.LPArray)] byte[] a, [MarshalAs(UnmanagedType.LPArray)] byte[] b, int size);2.1 Note that the 2 array parameters are decorated with MarshalAsAttributes that indicate that they are to be marshaled as C-style arrays.
2.2 Because the byte type in managed code is blittable, as an optimization, the CLR will pin the byte array when marshaling it to unmanaged code. See Copying and Pinning.
2.3 Specificically, read the section "Reference Types" beginning with "If a reference type is passed by value and it has only members of blittable types, it can be pinned during marshaling and any changes made to the members of the type by the callee are seen by the caller...".
2.4 By using the above mentioned automatic pinning optimization, you are allowed to make changes to the elements of the byte array in the unmanaged code and the value changes will be permanent (the C# code will see the updated values).
3. I hope the above information has been relevant and helpful to you.
- Bio.
Please visit my blog : http://limbioliong.wordpress.com/
- Marked As Answer by Helen ZhaoModerator Monday, May 07, 2012 2:07 AM
-
Sunday, April 29, 2012 5:28 AM
Please dont link me to another thread I cant find any that help, if you cant correct my code for me dont bother posting i'm fed up of my posts going wildly off topic...
__declspec(dllexport) bool BlankEqualPixels(char* a, char* b, int size){ for(unsigned int i=0; i<size; i+=4) { if(a[i]==b[i]&&a[i+1]==b[i+1]&&a[i+2]==b[i+2]){ a[i]=a[i+1]=a[i+2]=a[i+3]=0; } } return true; }
Curiously, I found that if you add an extra level of indirection, it makes it quite easy to implement the call from the C# side. For example, if we change the C++ code to:
extern "C" __declspec(dllexport) bool BlankEqualPixels (char** A, char** B, int size) { char* a = *A; char* b = *B; for(unsigned int i=0; i<size; i+=4) { if(a[i]==b[i]&&a[i+1]==b[i+1]&&a[i+2]==b[i+2]){ a[i]=a[i+1]=a[i+2]=a[i+3]=0; } } return true; }Then a sample of the C# could could be written as:
public class Program { [DllImport ("MyLib.dll")] private extern static bool BlankEqualPixels (ref byte[] a, ref byte[] b, int size); static void Main (string[] args) { byte[] a = new byte[4]; // create new byte stream a[0] = 0; a[1] = 1; a[2] = 2; a[3] = 3; byte[] b = new byte[4]; // create new byte stream b[0] = 0; b[1] = 1; b[2] = 2; b[3] = 3; BlankEqualPixels (ref a, ref b, 4); }
- Proposed As Answer by Helen ZhaoModerator Wednesday, May 02, 2012 6:11 AM
- Marked As Answer by Helen ZhaoModerator Monday, May 07, 2012 2:07 AM
-
Sunday, April 29, 2012 6:56 AM
It runs with no exceptions...
[DllImport("imgproc.dll", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] internal static extern bool BlankEqualPixels([MarshalAs(UnmanagedType.LPArray)]ref byte[] a, [MarshalAs(UnmanagedType.LPArray)]ref byte[] b); NativeMethods.BlankEqualPixels(ref buf1, ref lastframe);and the dll code:
__declspec(dllexport) bool BlankEqualPixels(unsigned char* a, unsigned char* b){ for(int i=0; i<sizeof(a); i+=4) { if(a[i]==b[i]&&a[i+1]==b[i+1]&&a[i+2]==b[i+2]){ a[i]=a[i+1]=a[i+2]=a[i+3]=0; } } return true; }BUT
when I use LPArray it returns buf1 as a single byte in length with the first byte unchanged
when I use SafeArray it returns all the bytes but they are not modified in any way.
Sorry I was frustrated but I am autistic and I only posted here because Crescens2k said I would get better support here.
- Edited by I installed vista on my bin Sunday, April 29, 2012 7:20 AM
-
Sunday, April 29, 2012 8:36 AM
You should pass the number of bytes as a parameter because sizeof(a) has a different meaning.
Sometimes you can do the job in C# too using unsafe and fixed keywords.
- Edited by Viorel_MVP Sunday, April 29, 2012 8:39 AM
- Proposed As Answer by Helen ZhaoModerator Wednesday, May 02, 2012 6:11 AM
- Marked As Answer by Helen ZhaoModerator Monday, May 07, 2012 2:07 AM
-
Sunday, April 29, 2012 3:17 PMI actually said the C# forums, and I did leave a sample of how to P/Invoke in the original thread ~10 hours ago.
This is a signature
Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this. -
Sunday, April 29, 2012 8:47 PM
Oh I'm sorry I completely forgot I thought I posted the other thread in the C# forum I got completely mixed up.
Every time I try sending the size as a parameter I get access violation.
- Edited by I installed vista on my bin Sunday, April 29, 2012 8:47 PM
- Edited by I installed vista on my bin Sunday, April 29, 2012 8:48 PM
-
Sunday, April 29, 2012 9:51 PM
Your C# P/Invoke decleration doesn't actually match the C++ parameter list. When there is no size passed along with it then sizeof will get the size to be 4 (which is the size of a pointer in 32 bit code) and then do things normally. But when you start using size as a parameter then you start overrunning buffers and if size is large enough then you can go over to the next memory page and there you go, one access violation.
Your C++ arrays have the type of unsigned char *, which is roughly equal to unsigned char[] and this converts to a C# type of byte[]. But when you add a ref to the start of the type, then things change a lot. You see, ref byte[] is not the same as byte[]. For C++ types, this is closer to unsigned char &[], which is roughly the same as unsigned char *[] or unsigned char ** (using the C rules). Those refs in your C# decleration list is causing all of your problems.
Remove any ref keywords in your parameter list and please don't just stick them on to everything. The ref keyword should only be used when you have a value type that changes across a function call. So if your parameter is a reference type (which arrays are) or doesn't change then you just don't need to mark it as ref.
This is a signature
Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this. -
Monday, April 30, 2012 12:37 AM
Sorry to keep nagging you but I'm still getting access violation is there something I'm missing?
[DllImport("imgproc.dll", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] internal static extern bool BlankEqualPixels([MarshalAs(UnmanagedType.SafeArray)]byte[] a, [MarshalAs(UnmanagedType.SafeArray)]byte[] b, [MarshalAs(UnmanagedType.I4)]int size);
__declspec(dllexport) bool BlankEqualPixels(unsigned char* a, unsigned char* b, int size){ for(int i=0; i<size; i+=4) { if(a[i]==b[i]&&a[i+1]==b[i+1]&&a[i+2]==b[i+2]){ a[i]=a[i+1]=a[i+2]=a[i+3]=0; } } return true; }
- Edited by I installed vista on my bin Monday, April 30, 2012 12:40 AM
-
Monday, April 30, 2012 12:39 AM
Yes, you now switched to SafeArray for your unmanaged type, this is a completely different type. This should be LPArray.This is a signature
Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.- Proposed As Answer by Helen ZhaoModerator Wednesday, May 02, 2012 6:10 AM
- Marked As Answer by Helen ZhaoModerator Monday, May 07, 2012 2:07 AM

