|
Well, VB.Net Express is a free download. Also if my memory serves the Power Packs download includes the binaries. (can't guarantee that, I downloaded it some time ago. )
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
hi
i pick some rows in datagrid, how i can mark them ?
(show blue mark on each row)
i work in C# - windows mobile
thank's in advance
|
|
|
|
|
If you actually mean DataGridView than look at How to: Set Alternating Row Styles for the Windows Forms DataGridView Control[^], which should give you enough to get started.
If you do actually mean DataGrid then take a look at DataGrid Formatting[^].
For future reference you should make it clear exactly which type of DataGrid you are talking about. Also you could have saved us all some time by googling this yourself.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
|
Reflector ( Here[^] ) has a class diagramming add-on ( 100% Reflective Class Diagram Creation Tool[^] ), as well as dependency graph generators and loads of other goodies.
Excellent tool.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Hey Henry, first thanks for the reply...
I know both tools, but they dont help me, I need an software that generates non existing interfaces, so i can apply them on classes that has no implementation.
Ones again, thanks for the reply.
With great code, comes great complexity, so keep it simple stupid...
|
|
|
|
|
I have an unmanaged function with a signature as follows:
func1(unsigned __int16 arg1, unsigned __int16 arg2, unsigned __int16** arg3);
now this is being called in the correctly working unmanaged code as:
{
unsigned __int16 arg1;
unsigned __int16 arg2;
unsigned __int16* arg3;
unsigned int test;
....
test = func1(arg1, arg2, &arg3));
.........
.........
}
I have imported the function(func1()) in the managed c# code as:
[DllImport("SomeDLL.dll", EntryPoint = "func1")]
unsafe public static extern uint func1(UInt32 arg1, UInt32 arg2, out UInt32* arg3);
And I am calling this function in my code as:
{
........
UInt32 arg1;
UInt32 arg2;
UInt32* arg3;
uint test;
...........
test = func1(arg1, arg2, out arg3);
............
/* I am using arg3 value over here*/
if(arg3[0] == null)
{
....
}
}
Now my problem is, in the unmanaged code when I access the arg3[0], it gives me a value, but in the managed code it gives me a pointer, to elaborate:
When I watch arg3 in the watch window in unmanaged code it shows as an array with the arg3 as a pointer and its 0 index value just as a value:
Name Value
- arg3 0x0F031321
arg3 1
in managed code it is:
Name Value
- arg3 0x000000000F031321
*arg3 490799104
notice that in the drop down list above the unmanaged code simply has arg3 in the second line whereas the managed code has *arg3. So my guess is in the latter the first value of the array is a pointer.
Even when I import the function as:
[DllImport("SomeDLL.dll", EntryPoint = "func1")]
unsafe public static extern uint func1(UInt32 arg1, UInt32 arg2, UInt32** arg3);
and call it as:
{
........
UInt32 arg1;
UInt32 arg2;
UInt32* arg3;
uint test;
...........
test = func1(arg1, arg2, &arg3);
............
}
Again, I have the same problem in the managed code.
Can someone please point the errors in my marshaling, and suggest some solutions.
Appreciate all the help.
modified on Monday, September 28, 2009 4:06 PM
|
|
|
|
|
Hi,
two questions:
1. if the unmanaged items are unsigned __int16 , why are you modeling them as UInt32 ???
2. what is the purpose of arg3? it looks like an array, now who is going to allocate it? and who is going to read it and write it? My suggestion will depend on this.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
1. if the unmanaged items are unsigned __int16, why are you modeling them as UInt32???
I am just following an example where the functions that have been imported and are successfully working are using UInt32 for similar signatures. Does this make a difference though? Since it is going to be implicitly converted.
2. what is the purpose of arg3? it looks like an array, now who is going to allocate it? and who is going to read it and write it? My suggestion will depend on this.
arg3 is going to be allocated by the unmanaged code (I guess so, though it is defined in the managed code, as I showed in the code snippet), it is written by the unmanaged function in the DLL whose code/implementation I do not possess. The managed code that I am writing should be able to access/read the arg3 array data, e.g.; if(arg3[0] == null){...}.
|
|
|
|
|
Hi,
1.
yes it can generate correct results, but it isn't a good habit. And it would go wrong if you did similar things with other type pairs, e.g. float and double. I expect it would also cause problems with arrays.
2.
AFAIK managed code can't accept an unmanaged array simply by applying a couple of * or & symbols.
This is the only way I know would work:
- declare an IntPtr variable
- accept the pointer as a "ref IntPtr" or "out IntPtr"
- create a managed array of correct size
- use Marshal.Copy to copy the data from the IntPtr (=unmanaged data) to the new, managed array
FYI: I very much prefer the approach where the managed code creates an array, passes it (as a pointer) to the unmanaged side, which fills it; that however is not how your unmanaged code works right now.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Time to get published, I think!
|
|
|
|
|
My article as of yet wouldn't really help here, as this is a situation I advise against. I suggest objects (and hence arrays) be created on the managed side. I might add my suggestion into the article though.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
I did as follows:
DllImport("SomeDLL.dll", EntryPoint = "func1")]
unsafe public static extern uint func1(UInt32 arg1, UInt32 arg2, ref IntPtr arg3);
And I am calling this function in my code as:
{
........
UInt32 arg1;
UInt32 arg2;
IntPtr arg3 = IntPtr.Zero; //made arg3 as Intptr
int [] managedArray = new int[1]; //created a managed array
uint test;
...........
test = func1(arg1, arg2, ref arg3);
............
/* I am using arg3 value over here*/
Marshal.Copy(arg3, managedArray, 0, 1);
if(managedArray[0] == null)
{
....
}
}
When I watch the managedArray[0] now, it still shows the values as before, kind of garbage values.
I am just writing a single value in the array (as indicated by the last param of Marshal.Copy because only one value is of interest).
Single indirection with out didn't help either.
modified on Monday, September 28, 2009 4:06 PM
|
|
|
|
|
Hi,
your code seems fine, it is what I would do given your description of the situation at hand.
except for the "I am using arg3 value over here" comment which doesn't fit the following line...
To debug, I would set up a slightly larger experiment, that generates say some 10 to 100 numbers of known value (mostly different), and dump the results to see if anything throws and/or anything gets recognized; I tend to use hex notation for debugging, and logging (i.e. write to console or file, not rely on watch windows).
If that doesn't help, I would allocate a managed array, fill it with numbers 1...N and pass its pointer (using GCHandle) to the native side, then watch the array when it returns.
[ADDED]
BTW: when copying the data from an unmanaged to a managed object/array, you now have two objects; you should not forget to get rid of the unmanaged object somehow (i.e. if the native code did a malloc, you should call a function that performs a free).
[/ADDED]
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
modified on Monday, September 28, 2009 4:03 PM
|
|
|
|
|
your code seems fine, it is what I would do given your description of the situation at hand.
except for the "I am using arg3 value over here" comment which doesn't fit the following line...
I have edited this in my previous message now.
To debug, I would set up a slightly larger experiment, that generates say some 10 to 100 numbers of known value (mostly different), and dump the results to see if anything throws and/or anything gets recognized; I tend to use hex notation for debugging, and logging (i.e. write to console or file, not rely on watch windows).
How do you write these data in hex form to the file. Using System.Diagnostics.Debug? I am new to this environment.
If that doesn't help, I would allocate a managed array, fill it with numbers 1...N and pass its pointer (using GCHandle) to the native side, then watch the array when it returns.
I did try this earlier but without using the GCHandle. This is what I did:
DllImport("SomeDLL.dll", EntryPoint = "func1")]
unsafe public static extern uint func1(UInt32 arg1, UInt32 arg2, ref Uint32[] arg3);
And I am calling this function in my code as:
{
........
UInt32 arg1;
UInt32 arg2;
//IntPtr arg3 = IntPtr.Zero; //made arg3 as Intptr
Uint32 [] managedArray = new Uint32[1]; //created a managed array
uint test;
...........
test = func1(arg1, arg2, ref managedArray);
............
/* I am using arg3 value over here*/
if(managedArray[0] == null)
{
....
}
}
It gives a similar kind of garbage value though.
I will try it with GCHandle, probably that will make it more accessible (or is it the only way to make it accessible?) to the unmanaged code.
Thanks
[ADDED]
BTW: when copying the data from an unmanaged to a managed object/array, you now have two objects; you should not forget to get rid of the unmanaged object somehow (i.e. if the native code did a malloc, you should call a function that performs a free).
There is another function that I have imported from the dll that frees the memory allocated by the unmanaged code:
public static extern uint freeMemory(IntPtr arg);
[/ADDED]
modified on Monday, September 28, 2009 4:36 PM
|
|
|
|
|
Hi,
1.
myInt.ToString("X8") turns an int into an 8-digit hex string;
and File.AppendAllText(filename,text) appends some text to a new or existing file
(there are faster ways with File.AppendText if lots of texts need appended).
2.
There are two explicit ways to get a pointer (to array or some other object); one is with the fixed keyword, the other with GCHandle, like so:
int dim=1000;
int[] numbers=makeIntArray(dim);
GCHandle handle=GCHandle.Alloc(numbers, GCHandleType.Pinned);
int sum=SumArray(handle.AddrOfPinnedObject(), dim);
handle.Free();
[DllImport("NativeC.dll")]
public static extern int SumArray(IntPtr pNumbers, int count);
3.
You do have native code that successfully calls the native lib, you said?
so you can read the calling code and understand exactly how it needs to be called, e.g. who is allocating the array.
If unclear, you could post some of that too.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
3.You do have native code that successfully calls the native lib, you said?
so you can read the calling code and understand exactly how it needs to be called, e.g. who is allocating the array.If unclear, you could post some of that too.
I have mentioned the native codes dll function signature, and how the native code calls it in my first post, if that's what you mean.
BTW I also found this http://msdn.microsoft.com/en-us/magazine/cc164193.aspx[^] article, with the mentioned PInvoke Interop Assistant application I got the result for this signature:
unsigned int func(unsigned __int16 arg1, unsigned __int16 arg2, unsigned __int16** arg3);
as this:
[System.Runtime.InteropServices.DllImportAttribute("<SomeDLL.dll>", EntryPoint="func")]
public static extern uint func(ushort arg1, ushort arg2, ref System.IntPtr arg3);
Which is exactly what you mentioned earlier. Have you used this application? If you have, what is your opinion about it?
I'll get back to you with the results for points 1 and 2.
Appreciate your suggestions.
|
|
|
|
|
I created an int array of size 1000 and initialized it from 0-999. Then I passed its GCHandle to the dll function. I changed the dll function signature to take the third argument as IntPtr. The array gets written to only in its first two indexes. With a kind of memory location address (not hex) or garbage value in index 0, and 0 in index 1 (everytime).
|
|
|
|
|
akhanal wrote: a kind of memory location address (not hex)
a number never is hex nor decimal, it is just a number; it is only input/output that turns it in to a string, which may be decimal, hex, binary, whatever you choose.
is the number a multiple of 4? if so, and probably is a pointer.
now do you have C code that successfully calls your func1?
can you make that work?
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Yes I have a c code that successfully calls the func1 in the dll and it is working as desired.
[ADDED]BTW do you know of any books that exclusively handles the interops (focusing on c#) and its shenanigans. Including but not limited to datatype marshaling, callbacks both ways, threading, P/Invoke, etc.[/ADDED]
Thanks
|
|
|
|
|
akhanal wrote: Yes I have a c code
Then show it here, so we can lift some doubts.
akhanal wrote: any books
No. Some articles yes. And I am in the middle of writing my own.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
Here is the modified code for the function that calls func1(getList()) and other functions from the dll:
void listTheMembers(unsigned __int16 ID1, unsigned __int16 ID2)
{
unsigned __int16* arg3;
int i;
unsigned int test;
printf("\nMembers in list %d on server %d:\n", ID2, ID1);
if((test = getList(ID1, ID2, &arg3)) != 0)
{
printf("Error getting member list for %d: %d\n", ID2, test);
return;
}
if(!arg3[0]) {
printf("No members\n\n");
freeTheAllocatedMemory(arg3);
return;
}
for(i=0; arg3[i]; i++)
{
char* nameOfMember;
if((test = getName(ID1, arg3[i], Member_Username, &nameOfMember)) != 0)
{
printf("There was an error in querying member's username: %d\n", test);
break;
}
printf("%u - %s \n", arg3[i], nameOfMember));
freeTheAllocatedMemory(nameOfMember);
}
printf("\n");
freeTheAllocatedMemory(arg3);
}
The signatures for the called functions are:
unsigned int getList(unsigned __int16 ID1, unsigned __int16 ID2, unsigned __int16** result);
unsigned int freeTheAllocatedMemory(void* ptr);
unsigned int getName(unsigned __int16 ID1, unsigned __int16 MemberID, size_t flag, int* MemberName);
No. Some articles yes. And I am in the middle of writing my own.
That's great, it will be awesome to read one.
modified on Tuesday, September 29, 2009 11:11 AM
|
|
|
|
|
seeing the real function name, and example code using it, I now know the native function is allocating an array and setting its pointer through arg3 (which you later must free again). So you don't need any fixed nor GCHandle and this code of yours[^] should be pretty close. However your int [] managedArray = new int[1] is still wrong, they are 16-bit numbers, so use short!
Check again in the way I indicated here[^].
When in doubt, compare results for a native caller and your managed caller.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|
I am receiving following values in the index 0 of the array, and index 1 is always 0:
504150240
504150256
504150272
504150288
504150880
504150896
504150912
504150928
504150944
504150960
It looks like address values.
|
|
|
|
|
That most probably isn't hex as I see 9 digits (for a 16-bit number???); it takes hex to get maximum probability of seeing a pattern if there is one.
Luc Pattyn
Local announcement (Antwerp region): Lange Wapper? Neen!
|
|
|
|
|