|
Hi Tom,
1.
please read again my earlier post about the padding bytes, and check it for the C side.
I am rather sure it is true C/C++ inserts them. You should verify to make absolutely sure.
My claim is: a C struct {char; int;} will have a size of 8, and probably
a C struct {int; char;} will too. Please check both.
2.
where you write
[FieldOffset(5), MarshalAs(UnmanagedType.Struct, SizeConst=64)]
I would replace 5 by 8 as explained before,
and I would drop the SizeConst=64 since that applies only to arrays and strings, not structs
(so I guess you could drop the MarshalAs(UnmanagedType.Struct too since that does not
add any information)
3.
my remark about IntPtr was not to the point; it applies to classes (in case you dont need
them), it does not apply to structs. For structs whose value you dont need you can omit them,
as long as you keep the FieldOffset values correct.
(Temporarily) omitting some substructs may help you in verifying that the Marshaling of
the remainder succeeds (before you got all the details right in those omitted substructs).
4.
You can always instantiate a struct and get its Marshal.Sizeof() which means the number
of bytes that will cross the border given the current information (as in FieldOffset
and MarshalAs attributes). This sizeof should match the C-side sizeof() value.
So I suggest you add logging to both sides to actually see them.
|
|
|
|
|
Hi.
I tried what you suggested and came up with the conclusion that there is no extra padding for structs.
The 64 bytes I calculated is the same size i got from Marshal.SizeOf and from the C code.
What I also found out is that you cannot use LayoutKind.Explicit and FieldOffset in a struct that has both values and refrences (or with refrences at all).
Check out Mattias Sjögren reply here:
http://www.dotnet247.com/247reference/msgs/5/27796.aspx[^]
So I worked around (I hope) the union problem by creating a struct that contains those two fields, and now it looks like this:
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct vc1_sBlk<br />
{<br />
public vc1_eBlkType eBlkType; <br />
public byte Coded; <br />
public union u;
};<br />
<br />
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct union<br />
{<br />
<br />
public vc1_sBlkIntra sIntra; <br />
public vc1_sBlkIntra sInter; <br />
};
So now these structs are completely managed and there is no need for the explicit layout anymore. Hwever, this didn't dolve the problem, which leads me to belive that I have asked the wrong question.
The original problem came up when I tried to do this:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public vc1_sBlk[] sBlk;
And no matter what I tried to marshal 'vc1_sBlk' or 'vc1_sBlkIntra', I kept getting the exception. So i tried removing the structures (which are refrences AFAIK) from 'vc1_sBlk' and it worked. Then I returned the structures, but changed the decleration to
public vc1_sBlk sBlk;
and it also worked. Everything is accessible and works fine.
So the question is can I declare a marshalled array that has refrences in it, and if not (which I assume is the case), how can I work around it?
Tom
(Sorry I am pouring all this data on you. I am just trying to be detailed to help you help me, and anyone else who should encounter this problem).
|
|
|
|
|
Hi Tom,
I am afraid you've lost me somehow.
1.
For unions the only way out I know in C# is by using FieldOffset.
Your "struct union" is not a union at all, it is a struct with two (sequential) members.
Of course, if the members are small, and the other side is flexible (i.e. no set of registers
cast in hardware, and no software in OBJ/EXE-only form, and no implicit conversion, see below)
then you could change it in this way, but it is a change, it is no longer what was intended
originally.
If you rely on union members to occupy the same memory (e.g. when you write to one member
then read the other to obtain a bit-wise translation, such as 4 bytes to 1 int), then you
need real unions of course.
2.
TomWolfstein wrote: The 64 bytes I calculated is the same size i got ...
I dont know which struct you refer to. If it is struct vc1_sBlkIntra, then we agree that
the size is 64B; and there is no need for padding, every member is short/ushort so they
all automatically align. If however it is vc1_sBlk from your original post
typedef struct
{
vc1_eBlkType eBlkType; /** Block type */
FLAG Coded; /** Non zero AC coefficients for Intra,
non zero AC/DC for Inter */
union
{
vc1_sBlkIntra sIntra; /** Intra block state information */
vc1_sBlkInter sInter; /** Inter block state information */
} u; /** Intra/Inter union */
} vc1_sBlk;
then depending on the size of vc1_eBlkType (lets say multiple of 4B) and FLAG (1B?)
I expect padding bytes to get the union aligned to a 4B multiple on the C/C++ side,
and also on the C# side (assuming Sequential, otherwise everything may get reordered).
3.
structs are value types, not references.
arrays are references, unless they are in a struct and carry marshaling info to tell
otherwise (ByValArray and SizeConst).
Marshaling references is complex, each pointer points to some memory block that
sooner or later may have to be a managed object. When given the choice, I tend to keep
things as simple as possible in marshaling, e.g. by putting everything as values in
one (big) struct, and by passing reference types one by one, using function calls
instead of struct members; and by avoiding structs/classes that contain references
all together (if needed, one can pass a null reference, then call a function to
accept a reference type and adapt the reference).
4.
I am getting confused about your structs; there are an unknown number of them, and they
have difficult names. So if you want detailed help, please be as specific and complete
as you can (and show both C and C# side as you did in your original post).
5.
it has been my experience one must build up the p/invoke and marshaling knowledge
by starting of with simple cases, observe them in detail, and get them to work
(compile, run without exception, pass the right data, checked by logging and/or
returning as a function result what was passed in).
And then gradually try more complex things. It is in general a bad idea to throw in all
the structs and classes at once, and have limited observability: it keeps you guessing
and probably wasting lots of time.
I tend to include logging code that dumps all the values that cross the borders,
I switch it on or off with one flag, and I leave the code in after I got it working,
so as soon as a functional change is required, it is there to help...
Hope this helps.
|
|
|
|
|
Hi.
Sorry it took me so long to answer. It's exam period..
I'll start with the end. I completley agree that it's best to learn P/Invoke and the principles of marshaling unmanaged code to managed code, and that simple examples should come before diving into a project like this.
I wish I knew all this 3 month ago when I started this. I didn't, and didn't have much choice as I am not writing this for my pleasure but as a final project for my degree. I am as unhappy with this as much as you can imagine. I want to thank you again for taking the time to explain all of this to a newbie like me.
Besides, don't they always say the best way to learn to swim is to just dive in
Now back to the fun (?).
1. I understand the structure I created to replace the union is not a good idea. I tried it as a way of getting the structure containing to occupy the same size it would have, had I used a union.
Now that I think the problem is somewhere else I can probably (hopefuly) change it back.
2. You are probably right here again. When I tried to offset the union 8 bytes, the alignment error disappeared and was replaced by the error caused by trying to marshal an array of structs.
Maybe this is because some of these structs have marshaled arrays in them.
4. Trust me, you are not the only obe confused by these structs, but as I said at the begining, the C source code is not mine. It is an open source implementation of the VC1 video standart. I'll be happy to send it to you if you are interested.
Meanwhile, I'll try to be clearer. I imported all of structs from the C code to C#, and marshalled all of them.
Basicaly there are two structures who contain in them, by way of value, reference and other, all of the other structures in the code.
I am sending an IntPtr from the C# code to the VC1 decoder (C code), and return that IntPtr with the address of the structure I want to access (I do it with 'out' rather than actually returning it, but the result is the same).
Right now some of the fields in the super struct (int C#) are garbage, and some are perfectly accessible. I think (and please correct me if I am wrong. there is a good chance I am), that this is because I did not import and marshall ALL of the structs, and this is causing an alignment error in the C# super struct, making it not the same size as the C code struct.
I have this struct 'vc1_sMB':
<br />
[StructLayout(LayoutKind.Sequential)]<br />
<br />
public unsafe struct vc1_sMB<br />
{<br />
vc1_eMBType eMBType; <br />
vc1_eACPred eACPred; <br />
vc1_eBlkType eBlkType; <br />
byte OverlapFilter; <br />
byte Skipped; <br />
byte CBPCY; <br />
byte MVBP; <br />
vc1_sQuant sQuant; <br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public vc1_sBlk[] sBlk; <br />
<br />
<br />
};
As you can see in the last line, there is a marshaled array of 'vc1_sBlk' structs.
The C version of this struct is exactly the same apart ftom the marshaled array, and I left the arrays original definition commented.
'vc1_sBlk' looks like this (now marshaled like you said to implement the union):
<br />
[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Ansi)]<br />
public unsafe struct vc1_sBlk<br />
{<br />
[FieldOffset(0), MarshalAs(UnmanagedType.I4)] public vc1_eBlkType eBlkType;<br />
<br />
<br />
[FieldOffset(4), MarshalAs(UnmanagedType.U1)] public byte Coded; <br />
<br />
<br />
[FieldOffset(8)] public vc1_sBlkIntra sIntra; <br />
[FieldOffset(8)] public vc1_sBlkIntra sInter; <br />
};
While it's original definition in the C code is this (FLAG is a 1B short):
typedef struct<br />
{<br />
vc1_eBlkType eBlkType; <br />
FLAG Coded; <br />
union<br />
{<br />
vc1_sBlkIntra sIntra; <br />
vc1_sBlkInter sInter; <br />
} u; <br />
} vc1_sBlk;
And as you've seen before 'vc1_sBlkIntra' looks like this in c#(the C code is in comments):
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct vc1_sBlkIntra<br />
{<br />
ushort NZC; <br />
<br />
short DC; <br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public short[] ACTop; <br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public short[] ACLeft; <br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public short[] moothRows;<br />
<br />
};
And 'vc1_sBlkInter' looks like this:
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct vc1_sBlkInter<br />
{<br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public ushort[] NZC; <br />
<br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public vc1_sMotion[] sMotion;<br />
<br />
} ;
I will not bother you with all the definitions of the other structures (everything that starts with an s, since there is nothing interesting there but normal type variables).
So 'vc1_sBlk' has in it structures that contain marshaled arrays (which like you said are references, if it matters).
All of this compiles without problem, but after I changed the offset to what you suggested, the error I got is this:
Cannot marshal field 'sPosition' of type 'vc1DEC_sState': The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable.
(I apologize. This really is never ending)
'vc1DEC_sState' is this (only the first line is important, but I pasted all of it):
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct vc1DEC_sState<br />
{<br />
public vc1_sPosition sPosition; <br />
vc1_sPicture pPicture; <br />
<br />
public int FrameNum; <br />
<br />
<br />
vc1_sMB pMB; <br />
<br />
<br />
<br />
int NumFields; <br />
int MaxMBs; <br />
vc1_sLevelLimit pLevelLimit; <br />
<br />
<br />
vc1_sSequenceLayer sSeqParams; <br />
vc1DEC_sPictureLayerParams sPicParams; <br />
<br />
byte NotFirstMode3InFrame; <br />
<br />
byte LevelCodeSize; <br />
byte RunCodeSize; <br />
<br />
byte ZigZagTableIndex; <br />
byte FirstFrameInStream; <br />
byte BitplaneCodingUsed; <br />
<br />
byte FirstCodedBlock; <br />
<br />
public vc1_sReferencePicture pCurrentRef; <br />
<br />
<br />
vc1_sMotionHist pMVHistBuffer; <br />
uint FieldCount; <br />
<br />
}
And inside it, the 'sPosition' mentioned is this (again just notice that vc1_sMB is defined here):
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public unsafe struct vc1_sPosition<br />
{<br />
vc1_ePictureType ePictureType; <br />
vc1_ePictureFormat ePictureFormat; <br />
vc1_eProfile eProfile; <br />
vc1_eMVMode eMVMode; <br />
vc1_eMVRange eMVRange; <br />
byte BottomField; <br />
byte SecondField; <br />
vc1_sMB pCurMB; <br />
vc1_sMB pStartMB; <br />
vc1_sMotionHist pMVHist; <br />
uint SizeMB; <br />
ushort X; <br />
ushort Y; <br />
ushort SliceY; <br />
ushort WidthMB; <br />
ushort HeightMB; <br />
public uint CodedWidth; <br />
public uint CodedHeight; <br />
uint MaxCodedWidth; <br />
uint MaxCodedHeight; <br />
byte PQuant; <br />
byte BFraction; <br />
byte NumRef; <br />
byte RefField; <br />
byte IntraBias; <br />
byte RangeYScale; <br />
byte RangeUVScale; <br />
byte FastUVMC; <br />
vc1_ePictureRes ePictureRes; <br />
vc1_sReferencePicture pReferenceOld; <br />
vc1_sReferencePicture pReferenceNew; <br />
vc1_sReferencePicture pReferenceB; <br />
vc1_sReferencePicture pReferenceNoIC; <br />
<br />
<br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]<br />
public vc1_sScaleMV[] pScaleMV; <br />
<br />
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6*64)] public short[] pSmooth;<br />
} ;
All of this brings us back to the begining (did I apologize already for the length of this?)
If you remember in the begining of this post, 1e100000000000 lines above, I said that the last line of 'vc1_sMB' is the declaration of a marshaled array of 'vc1_sBlk'.
If instead of this array I declare this:
public vc1_sBlk sBlk; /** Block level information */ Then there is no error.
I can't get access to all of the fields in all of the structs, but at least there is no error.
So, finally, I suspect this array.
Am I right to suspect it?
Am I on the right way to gain normal access to the structs fields?
Would it help if I sent you the C code?
I did not intend for this to be the longest post ever. I am deeply thankful for the time you are putting into just reading all of this, not to mention trying to understand and come up with solutions.
Thanks.
Tom.
|
|
|
|
|
Hi Tom,
1.
yes I would like to have the C code in a compilable and runnable form. Please email it
using the email button below. Have some questions:
1.1. Which tool do you use to build it ? (I hope Visual Studio 6)
1.2. Does it use "normal" sizes (1B byte, 2B short, 3B int, ...) ?
1.3. Where did you get the source exactly ?
1.4. Did you change anything ? If so did you comment that in the source ?
1.5. Did you add code to print out:
- struct sizes ?
- and field offsets ? Are they what you expected ?
- field values ?
2.
I entered your C# code in a C# project, but I am missing a lot:
several vcl_### types such as vc1_eMBType; I hope most of them are int enums.
I think you best also send me the source of C# class that is supposed to call the C stuff.
3.
to access vc1DEC_sState.sPosition one must get all its members marshalled (almost) correctly;
as long as something is wrong in say vc1_sPicture, it will continue to give that kind
of run-time errors.
And that's exactly why I tend to build a marshalling job from bottom to top,
so you get something working and this gives you the energy to continue...
4.
Are you sure you need the unsafe keyword ? what is it supposed to bring you ?
5.
some of your fields are public, most of them not. Why is this ?
If you dont need to access most of the fields in C#, you can replace them by something simpler
having the same size (such as vc1_sMB in vc1DEC_sState !?!?
Greetings
|
|
|
|
|
Hi Tom,
FYI: in C# the following struct
[StructLayout(LayoutKind.Sequential)]<br />
public struct ccc {<br />
int a1;<br />
byte b1;<br />
int a2;<br />
byte b2;<br />
int a3;<br />
byte b3;<br />
}
has a Marshal.Sizeof of 24 as I expected; each byte gets followed by 3 padding bytes
to align the next int.
And that is also how I recall it from C (I did not test that now).
|
|
|
|
|
how i can validate a formula.
formula contains column names of a table..
pls help for this
Lakshmi
|
|
|
|
|
What formula?
modified 12-Sep-18 21:01pm.
|
|
|
|
|
hi guyz..
Any one know how to make a datagrid with checkbox in each row(email style),
I will use it for multiple selection, I'm using c#.net 2003.. I want my application to have this feature..
tnx in advance n_n
|
|
|
|
|
Hey
Try this link for some hints:
http://www.asp.net/learn/dataaccess/tutorial12cs.aspx?tabid=63
Hope it helps
Dan
|
|
|
|
|
Hi all,
I have try to convert a pdf to tiff file.My below the code snippet is working fine when i open a tiff file and convert some other format..But it didn't work when i open the pdf file,it will be thrown error like "Parameter is not valid" from below the code at bold line "Image image = Image.FromStream(fromImageStream, false,true);" please help me what i did wrong.
private void button4_Click(object sender, System.EventArgs e)<br />
{<br />
<br />
FileStream fstPersons = new FileStream(@"c:\\toto.tiff",<br />
FileMode.Create,FileAccess.Write);<br />
BinaryWriter wrtPersons = new BinaryWriter(fstPersons);<br />
<br />
FileStream fStream = new FileStream(@"c:\\Sample.pdf", FileMode.Open,<br />
FileAccess.Read);<br />
BinaryReader reader = new BinaryReader(fStream);<br />
<br />
FileInfo info = new FileInfo(@"c:\\sample.pdf");<br />
<br />
byte[] fromImage = null;<br />
<br />
fromImage = reader.ReadBytes((int)info.Length);<br />
<br />
reader.Close();<br />
fStream.Close();<br />
<br />
MemoryStream fromImageStream = new MemoryStream();<br />
fromImageStream.Write(fromImage, 0, fromImage.Length);<br />
Image image = Image.FromStream(fromImageStream, false,true);<br />
Bitmap bitmap = (Bitmap)image;<br />
EncoderParameters encoderParams = new EncoderParameters();<br />
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 50L);<br />
ImageCodecInfo codecInfo = GetEncoderInfo("image/tiff");<br />
MemoryStream newImage = new MemoryStream();<br />
bitmap.Save(newImage, codecInfo, encoderParams);<br />
byte[] data = newImage.ToArray();<br />
<br />
wrtPersons.Write(data);<br />
<br />
fstPersons.Close();<br />
wrtPersons.Close();<br />
<br />
}<br />
<br />
<br />
<br />
private static ImageCodecInfo GetEncoderInfo(String mimeType)<br />
{<br />
int j;<br />
ImageCodecInfo[] encoders;<br />
encoders = ImageCodecInfo.GetImageEncoders();<br />
for(j = 0; j < encoders.Length; ++j)<br />
{<br />
if(encoders[j].MimeType == mimeType)<br />
return encoders[j];<br />
}<br />
return null;<br />
}<br />
thanks in advance
|
|
|
|
|
Stream operations are very much like good old file operations:
if you write a file, then want to read what has been written, you must either close and reopen,
OR somehow "rewind" the file. Look for an appropriate stream method
(or property) to do this...
|
|
|
|
|
hi
while reading a file named with underscore i am having error illegal characters found how can i remove it and how to find the particular position in a file
|
|
|
|
|
please be specific, show the error messages and Exception.ToString(), show the code,
tell us which parts work and which dont...
(so read and apply the forum guidelines !)
|
|
|
|
|
Hi,
I have the following hardcoded labels:
this.labelAWeekAgo1.Text = lastWeek.ToString();
this.labelAWeekAgo2.Text = lastWeek.ToString();
..
this.labelAWeekAgo10.Text = lastWeek.ToString();
with each individual label contained within a loop that contains a function with the result generating "lastweek".
How can I code the label variable that changes programatically ie the number at the end of the labels name depending on which pass thru the loop I'm in eg
for i=0 etc
this.labelAWeekAgo[i].Text = lastweek.ToString();
Glen Harvy
|
|
|
|
|
Use For loop
for(i=0;i<9;i++)
{
//your code
}
or you can use foreach which is more easy.
Details[^]
Regards,
Satips.
|
|
|
|
|
Thanks for the prompt reply.
I'm trying to avoid having to do the following for each hardcoded label:
Label[] lbThisWeek = new Label[10];
for (int i = 0; i < lbThisWeek.Length; i++)
{
lbThisWeek[i] = new Label();
}
lbThisWeek[0] = this.labelThisweek1;
lbThisWeek[1] = this.labelThisweek2;
lbThisWeek[2] = this.labelThisweek3;
lbThisWeek[3] = this.labelThisweek4;
lbThisWeek[4] = this.labelThisweek5;
lbThisWeek[5] = this.labelThisweek6;
lbThisWeek[6] = this.labelThisweek7;
lbThisWeek[7] = this.labelThisweek8;
lbThisWeek[8] = this.labelThisweek9;
lbThisWeek[9] = this.labelThisweek10;
Doing this allows me to use the loop to perform my actions but it seems I have to create separate arrays for each item as I can't see how you pass [i] to a hardcoded control name.
Glen Harvy
|
|
|
|
|
Hi,
create a collection of your labels (an array, an ArrayList, a List, whatever),
and foreach them.
If its all the labels on a form, you could also foreach your form's controls as in:
foreach (Control c in myForm.Controls) {
Label lbl=c as Label;
if (lbl!=null) doSomethingToLabel(lbl);
}
Finally you could use reflection to find all the labels with a specific name syntax,
but that seems overkill (and expensive) in this case.
|
|
|
|
|
Thanks,
Yes - it looks like an array for each label concerned is the easiest - thank heavens for search & replace.
Glen Harvy
|
|
|
|
|
Ho ho, I think no one suggested changing the label names; if you replace myLabel1 by
myLabel[1] the Visual Designer will no longer understand it (the declarations would
be wrong).
What you should do is keep the labels as they are, and on top of that create a list
(an array or some other collection) that holds references to them, so you can foreach it.
You could create and populate the list right after the call to InitializeComponents().
|
|
|
|
|
Create an array of references to your labels:
Label[] labelAWeekAgo = new Label[] { labelAWWeekAgo1, labelAWWeekAgo2, ... ,labelAWWeekAgo10};
Note that the index for the array is zero based.
If you use foreach to loop the array, you don't use an index:
string lastWeekString = lastWeek.ToString();
foreach (Label label in labelAWeekAgo) {
label.Text = lastWeekString;
}
---
single minded; short sighted; long gone;
|
|
|
|
|
Hi All,
I have developed a windows application using serial port.
Now, i am asked to convert it into a .exe file(console application)..Is it possible? if so, how can i do it??
could any one please help me...
Thanks in Advance.
|
|
|
|
|
Just create a console app and move your code into it. The main thing is, a console app does not have events, so you need to build your own menus and so on in plain text.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
I have done it in the same way...
ITs running well on my machine... But when I run that .exe file on another machines its saying
" application failed to initialize properly: Click OK to terminate the program"
whats the problem??
how can I run my .exe on another machines as well....???

|
|
|
|
|
There can be several reasons for this, try Google to see them.
Best guess is read access violation on some DLL file.
BTW the message typically includes an error code, if it did you should show it.
|
|
|
|
|