954,510 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Pascal to C# troubles.

I'm encountering some problems with converting Delpi7 pascal to C#, maybe a fresh set of eyes will see what I can't.


Pascal

procedure TForm1.Button5Click(Sender: TObject);
var Data: TData;
    i: integer;
    s: string;
begin
if not (CheckBox1.Checked) then
  begin StatusBar1.SimpleText:='Bidirectional operation not allowed'; exit; end;
for i:=0 to 255 do Data[i]:=0;
Data:=Receive($02,8);
if (Data[1]=0) then
  begin StatusBar1.SimpleText:='Failed'; exit; end;
s:='';
for i:=1 to 8 do
  s:=s+Chr(Data[i+1]);
Edit1.Text:=s;
end;


C#

private void btnRX_Click(object sender, EventArgs e)
        {
            byte[] Data = null;
            int i;
            string s;

            if (!(checkBox1.Checked))
            {
                toolStripStatusLabel1.Text = "Bidirectional operation not allowed";
                return;
            }
            for (i = 0; i <= 255; i++)
            {
                Data[i] = 0;
            }
            Data = Receive(0x02, 8);
            if ((Data[1] == 0))
            {
                toolStripStatusLabel1.Text = "Failed";
                return;
            }
            s = "";
            for (i = 1; i <= 8; i++)
            {
                s = s + (char)(Data[i + 1]);
            }
            txtBox1.Text = s;
        }

I crash at

Data[i] = 0;
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Forgot to add this part to the Pascal code

type
  TData = array [0..255] of byte;
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Think you got a null reference exeption.
You did not declare your byte array on line 3:
Use something like this in C#:

byte[] Data = new byte[256];
ddanbe
Senior Poster
3,829 posts since Oct 2008
Reputation Points: 2,070
Solved Threads: 661
 

You've declared a placeholder for the byte values (line 3), but didn't actually allocate them. Change it to byte[] Data = new byte[256]; .

No idea what Receive is supposed to do, so can't help you with that.

Momerath
Nearly a Senior Poster
3,384 posts since Aug 2010
Reputation Points: 1,232
Solved Threads: 558
 

Thank you ddanbe and Momerath!

I didn't see that at all.

correcting this has allowed me to step into the next error, "MarshalDirectiveException was unhandled" at Data = Receive(0x02, 8); most likely due to the microcontroller not responding to the Receive command.
Guess I need an error trap now.

Thanks again.

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

New problem, too tired to concentrate.

Taking the text data from textBox1, it gets sent to the micro controller one byte at a time, So the text needs to be converted to its numeric equivalent

In Delphi, Ord provides the Ordinal value of an integer, character or ... or enumerations into their numeric equivalents. What is the command in C#?

The second part is the reverse, pulling the data from the micro controller as numeric values and converting it.

In Delphi, Chr converts an integer into a character. What is the command in C#?


Original Delphi Pascal code:

procedure TForm1.Button3Click(Sender: TObject);
var Data: TData;                   
    i, Len: integer;               
begin
Data[0]:=$02;                      
for i:=1 to 8 do Data[i]:=$20;     
for i:=1 to length(Edit1.Text) do
  Data[i]:=Ord(Edit1.Text[i]);     //copy Data
Len:=8;
if (Send(Len,Data)) then StatusBar1.SimpleText:='OK' else StatusBar1.SimpleText:='Failed';
end;

procedure TForm1.Button5Click(Sender: TObject);
var Data: TData;
    i: integer;
    s: string;
begin
if not (CheckBox1.Checked) then
  begin StatusBar1.SimpleText:='Bidirectional operation not allowed'; exit; end;
for i:=0 to 255 do Data[i]:=0;
Data:=Receive($02,8);
if (Data[1]=0) then
  begin StatusBar1.SimpleText:='Failed'; exit; end;
s:='';
for i:=1 to 8 do
  s:=s+Chr(Data[i+1]);
Edit1.Text:=s;

Code Converted to C#:

private void btnTX_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[256]; 
            int i , Len;                 
            Data[0] = 0x02;              
            for (i = 1; i <= 8; i++) Data[i] = 0x20;
            for (i = 1; i <= txtBox1.Text.Length; i++)
                Data[i] = ord(txtBox1.Text[i]);     // <---Compile error here
            Len = 8;
            if ((Send(Len, Data))) toolStripStatusLabel1.Text = "OK"; else toolStripStatusLabel1.Text = "Failed";
        }
                private void btnRX_Click(object sender, EventArgs e)
         {
             byte[] Data = new byte[256];
             int i;
             string s;

             if (!(checkBox1.Checked))
             { toolStripStatusLabel1.Text = "Bidirectional operation not allowed"; return; }
             for (i = 0; i <= 255; i++) Data[i] = 0;
             Data = Receive(0x02, 8);
             if ((Data[1] == 0))
             { toolStripStatusLabel1.Text = "Failed"; return; }
             s = "";
             for (i = 1; i <= 8; i++)
                 s:=s+Chr(Data[i+1])  //<-----Compile error here
             txtBox1.Text = s;
         }
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Many options, have a look here: http://msdn.microsoft.com/en-us/library/f02979c7.aspx to convert a string to an int.
You could also use Convert it has among others the methods ToString and ToInt
Line 26 of your code could read: s = Data[i+1].ToString();
The assignment operator is = not :=!
In C# every type derives from Object, so you could even say something like MyStr = 123.ToString(); and MyStr would equal "123".

ddanbe
Senior Poster
3,829 posts since Oct 2008
Reputation Points: 2,070
Solved Threads: 661
 

Thanks ddanbe

s = s + Data[i+1].ToString();


fixed line 26, line 8 still under research.

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Well, look at the TryParse method here in the MSDN link I provided you in my previous post. There is some sample code.

ddanbe
Senior Poster
3,829 posts since Oct 2008
Reputation Points: 2,070
Solved Threads: 661
 

I continue to get Marshal errors,

[DllImport("mrdsio.dll", CallingConvention=CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.Interface)]
        public static extern byte[] Receive(int Adr, int Len);

private void btnRX_Click(object sender, EventArgs e)
         {
             byte[] Data = new byte[256];
             int i;
             string s;

             if (!(checkBox1.Checked))
             { toolStripStatusLabel1.Text = "Bidirectional operation not allowed"; return; }
             for (i = 0; i <= 255; i++) Data[i] = 0;

             
             Data = Receive(0x02,8);  <--ERROR "Cannot marshal 'return value': Invalid managed/unmanaged type combination."


             if ((Data[1] == 0))
             { toolStripStatusLabel1.Text = "Failed"; return; }
             s = " ";
             for (i = 1; i <= 8; i++)
                 s = s+Data[i + 1].ToString();
             txtBox1.Text = s;
         }


How do I Marshal both Adr and Len?

The mrdsio.dll acts like a Inpout32.dll using pseudo i2c to send/receive address pointer and data from a micro controller.

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 
#
[DllImport("mrdsio.dll", CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Ansi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool Send(int Len, byte[] Data);

private void btnTX_Click(object sender, EventArgs e)
         {
             byte[] Data = new byte[256];
             int i, j, Len;                
             Data[0] = 0x02;                          // buffer address
             j = txtBox1.Text.Length;
             for (i = 1; i <= 8; i++) Data[i] = 0x20; // fill 8 blank spaces first
             Len =8;
             if ((Send(Len, Data))) toolStripStatusLabel1.Text = "OK"; else toolStripStatusLabel1.Text = "Failed";
         }


Using the above code, I can correctly send 8 spaces (0x20), changing the 0x20 to 0x21 and it correctly fills the 8 spaces with !!!!!!!! (8 exclamation marks), so the function is working.

How do I define

Data[i] = "The next character in the txtBox1.text.string"
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 
for (int i = 0; i < textBox1.Text.Length, i++) {
    Data[i] = textBox1.Text[i];
}
Momerath
Nearly a Senior Poster
3,384 posts since Aug 2010
Reputation Points: 1,232
Solved Threads: 558
 

Thanks Momerath

that results in a an error
"Cannot implicitly convert type 'char' to 'byte'"

I'm missing something very basic here, just cant see it.

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Ok, got the code sorted out, the data is sending to the micro controller, but the data is parsing out the very first Data[i] char.

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

The Send function is now working, but the Receive function (the exact opposite function of Send) is still evoking errors.

Cannot marshal 'return value': Invalid managed/unmanaged type combination.
[DllImport("mrdsio.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern byte[] Receive(int Adr, int Len);

private void btnRX_Click(object sender, EventArgs e)
        {
            
            byte[] Data = new byte[256];
            int i;
            string s;
            int Adr = 0x02;
            int Len = 8;
            for (i = 0; i <= 255; i ++ ) Data[i] = 0;
            Data = Receive(Adr, Len);  <-------Error "Cannot marshal 'return value': Invalid managed/unmanaged type combination."
            if ((Data[1] == 0))
            {
                StatusLbl1.Text = "Failed, check Connection";
                return;
            }
            s = "";
            for (i = 1; i <= 8; i ++ )
            {
                s = s + (char)(Data[i + 1]);
            }
            txtBox1.Text = s;
            
        }
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Still having problems with this RECEIVE function.

The SEND function is the exact opposite function of Receive, I'm perplexed as to why I can send the data, but not retrieve it.

[DllImport("mrdsio.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern bool Send(int Len, byte[] Data);

[DllImport("mrdsio.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern byte[] Receive(int Adr, int Len);

private void btn_SEND_Click(object sender, EventArgs e)
        {
            byte[] Data = new byte[256];
            int i, Len;
            Data[0] = 0x02;             // buffer address
            Len = 8;
             for (i = 0; i < txtBox1.Text.Length; i++)
            {
                byte vOut = Convert.ToByte(txtBox1.Text[i]);
                Data[i + 1] = vOut;
            }
            if ((Send(Len, Data))) StatusLbl1.Text = "OK"; else StatusLbl1.Text = "Failed";
       }



        private void btn_RECEIVE_Click(object sender, EventArgs e)
        {
            int i;
            int Adr = 0x02;
            int Len = 8;
            string s = "";
            byte[] Data = new byte[256];
            
            for (i = 0; i <= 255; i ++ ) Data[i] = 0;
            
            Data = Receive(Adr, Len); <----------Cannot marshal 'return value': Invalid managed/unmanaged type combination.
              
            i = 0;
            while (i < Len-1 && Data[i] != 0)
            {
                s = s + Convert.ToChar(Data[i]);
                i++;
            }
            txtBox1.Text = s;
         }
SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Perhaps it has something to do with this: http://msdn.microsoft.com/en-us/library/chfa2zb8.aspx

ddanbe
Senior Poster
3,829 posts since Oct 2008
Reputation Points: 2,070
Solved Threads: 661
 

The original source code for the mrdsio.dll (.pas file) indicates that the function of Receive(Adr,Len) results in a String called OUTPUT.

Now if I am issuing Receive(Adr,Len) how would I get the mrdsio.dll's string of OUTPUT?

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

Did you try to compile your code marked as unsafe?

ddanbe
Senior Poster
3,829 posts since Oct 2008
Reputation Points: 2,070
Solved Threads: 661
 

ddanbe

No, It will compile as posted 3 messages above, but the Receive function wont work and will crash if the Receive function is run.

Trying to convert how Receive is handled/marshalled/processed from the Delphi6 original to C# is my hangup.

The original code for the mrdsio.dll handles the address, byte array and returns the results.

type

  TData = array [0..255] of byte;


function Receive(Adr, Len: Integer): TData;

function TDM1.Receive(Adr, Len: Integer): TData;

var Output: TData;

...
...
Result:=Output;[/CODE]

SteveyD
Light Poster
41 posts since Jan 2010
Reputation Points: 10
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You