Page 1 of 1

Hilfe bei Easylase.dll und C#

Posted: Thu 06 Mar, 2008 9:18 am
by jokakilla
Moin moin,
ich hab nach längerer Zeit mal wieder meine Anlage angeschmissen und mir natürlich den aktuellen Treiber für die Easylase runtergeladen. Habe dann gleich mal Lasertennis und Astroids ausprobiert und war schon ziemlich begeistert :)
Kurzum inspiriert davon wollte ich mich mal dran machen und was eigenes, bevorzugt in C#, programmieren. Ich stehe noch ganz am Anfang und komme leider nicht so recht weiter.
In der Dokumentation der DLL ist die Funktion zum Schreiben eines Frames wie folgt definiert:

Code: Select all

Function EasyLaseWriteFrame(CardNumber:integer, Datapointer:pointer,
Byteanzahl:integer, Punktspeed :word):boolean
Mein C# Code bisher:

Code: Select all

    public partial class Form1 : Form
    {
        [DllImport("easylase.dll")]
        public static extern int EasyLaseGetCardNum();
        [DllImport("easylase.dll")]
        public static unsafe extern bool EasyLaseWriteFrame(int cardNumber, byte[] datapointer, int bytecount, int speed);
        [DllImport("easylase.dll")]
        public static extern bool EasyLaseStop(int cardNumber);
        [DllImport("easylase.dll")]
        public static extern bool EasyLaseClose();

        private int easylaseCount;

        public unsafe Form1()
        {
            InitializeComponent();
            easylaseCount = EasyLaseGetCardNum();

            if (easylaseCount > 0)
            {
                byte[] frame = new byte[] { 0, 0, 0, 0, 255, 0, 0, 255, 128, 0, 0, 0, 255, 0, 0, 255 };
                EasyLaseWriteFrame(0, frame, 16, 5000);
            }
            
        }

        private void Form_Closing(object sender, EventArgs e)
        {
            if (easylaseCount > 0)
            {
                EasyLaseStop(0);
                EasyLaseClose();
            }
        }
    }

Das Funktioniert nicht :( Gibt mecker zur Laufzeit.
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Ich hab es auch schon mit diversen Varianten versucht z.B.

Code: Select all

  
        [DllImport("easylase.dll")]
        public static unsafe extern bool EasyLaseWriteFrame(int cardNumber, byte *[]datapointer, int bytecount, int speed);
              byte []frame = new byte[] { 0, 0, 0, 0, 255, 0, 0, 255, 128, 0, 0, 0, 255, 0, 0, 255 };
                fixed(byte *ptr = frame);
                EasyLaseWriteFrame(0, ptr, 16, 5000);
Da nörgelt der Compiler schon beim fixed(...) Warning möglicherweise falsche leere Anweisung.
EasyLaseWriteFrame(...) Error Der Name ptr ist im aktuellen Kontext nicht vorhanden.


Kann mir vielleicht jemand auf die Sprünge helfen? Eigentlich wäre ein zweidimensionales Array später doch auch einfacher zu handhaben oder? n*8 Byte. Wie macht man sowas mit Pointern in C#?

Ohne ist ja nicht schwer:

Code: Select all

byte[,] 3x3array = byte[,] {{0,1,2}, {0,1,2}, {1,2,3}};

Posted: Thu 06 Mar, 2008 9:54 am
by jojo
Sind die Beispiele für C++ nicht als Anhaltspunkt zu verwenden?

Bei Dir kommt nirgends die Call convention "__stdcall" vor.
Ich glaube aber, das ist wichtig, damit die Übergaben auf dem Stack passen.

Code: Select all

[DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)] 
oder so in etwa?

Joachim

Posted: Thu 06 Mar, 2008 10:12 am
by jokakilla
Hat leider nicht geholfen :(

Code: Select all

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace LaserTTT
{
    public partial class Form1 : Form
    {
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int EasyLaseGetCardNum();
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static unsafe extern bool EasyLaseWriteFrame(int cardNumber, byte *datapointer, int bytecount, int speed);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern bool EasyLaseStop(int cardNumber);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern bool EasyLaseClose();

        private int easylaseCount;

        public unsafe Form1()
        {
            InitializeComponent();
            easylaseCount = EasyLaseGetCardNum();

            if (easylaseCount > 0)
            {
                byte []frame = new byte[] { 0, 0, 0, 0, 255, 0, 0, 255, 128, 0, 0, 0, 255, 0, 0, 255 };
                fixed (byte *array = frame)
                {
                    EasyLaseWriteFrame(0, array, 16, 5000);
                
                }
                
            }
            
        }

        private void Form_Closing(object sender, EventArgs e)
        {
            if (easylaseCount > 0)
            {
                EasyLaseStop(0);
                EasyLaseClose();
            }
        }
    }
}
Gibt auch nen Fehler:
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

Posted: Thu 06 Mar, 2008 1:01 pm
by afrob
[DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
public static unsafe extern bool EasyLaseWriteFrame(int *cardNumber, byte *datapointer, int bytecount, int speed);
[DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool EasyLaseStop(int *cardNumber);

wäre einen Versuch wert.

Grüsse,
afrob

Posted: Thu 06 Mar, 2008 4:39 pm
by jojo
Hinweis:

"Speed" ist kein Integer.
Ein Integer hat (zumindest auf dem PC) 32Bit.
Speed ist aber ein 16 Bit-WORD (aus Delphi), also "unsigned short"!

Joachim

Posted: Thu 06 Mar, 2008 5:23 pm
by thomasf
Hi,

also ich kenne mich überhaupt nicht mit C# aus diese ganze .net geschichte nervt sowieso aber okay.

ich glaube der fehler liegt darin das du dein Frame array nicht vordeviniert hast. es muß [0..128000] byte groß sein und nicht dynamisch.

gruß thomas

Posted: Thu 06 Mar, 2008 6:05 pm
by jokakilla
Vielen Dank schonmal für eure Ideen.

Leider bleibt der Fehler bestehen :(
Hatte zwischenzeitlich die Cardnumber als Pointer deklariert wobei mir der Sinn auch nicht ganz klar ist.
Ops der Speed ist jetzt ein unsigned short (ushort). Thx.

Ich dachte eigentlich man müsse nur die Punkte definiere, die man auch setzen möchte. Das 128k Array bringt leider auch nichts. Habs schon extra nochmal mit nullen gefüllt obwohl das ja eigentlich auch uninitialisiert so sein sollte.
Typen Casten bei den Konstanten die ich übergebe hat auch nix genützt.

Der Code sieht jetzt wie folgt aus:

Code: Select all

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace LaserTTT
{
    public partial class Form1 : Form
    {
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int EasyLaseGetCardNum();
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static unsafe extern bool EasyLaseWriteFrame(int cardNumber, byte *datapointer, int bytecount, ushort speed);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static unsafe extern bool EasyLaseStop(int cardNumber);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern bool EasyLaseClose();

        private int easylaseCount;

        public unsafe Form1()
        {
            InitializeComponent();
            easylaseCount = EasyLaseGetCardNum();

            if (easylaseCount > 0)
            {
                byte[] frame = new byte[128000];
                for (int i = 0; i < 127999; i++)
                    frame[i] = 0;

                fixed (byte *array = frame)
                {
                    EasyLaseWriteFrame((int)0, array, (int)16, (ushort)5000);
                
                }
                
            }
            
        }

        private void Form_Closing(object sender, EventArgs e)
        {
            if (easylaseCount > 0)
            {
                EasyLaseStop(0);
                EasyLaseClose();
            }
        }
    }
}

Posted: Thu 06 Mar, 2008 7:20 pm
by jokakilla
Also ich hab mal weiter geforscht. Wenn ich die AccessViolationException beim WriteFrame abfange tritt die nochmal beim EasyLaseStop(0); auf.

Es sei denn ich führe vor dem EasyLaseStop(0) nochmal EasyLaseGetCardNum() aus.

Posted: Tue 11 Mar, 2008 4:18 pm
by jokakilla
Ich konnte das Problem mit der Hilfe von einem User von mycsharp.de lösen.

Es lag an den Parametern. Kann es sein, dass die Dokumentation der EasyLase.dll nicht richtig ist? In dem PDF steht, dass es sich bei dem cardNumber Parameter der EasyLaseWriteFrame Funktion um einen Integer handelt. Tatsächlich muss es ein Pointer auf einen Integer sein.



Naja ich werd für den Anfang mal versuchen TicTacToe zu Programmieren um erstmal damit warm zu werden. Bin allerdings was Grafiksachen angeht nicht so erfahren.

Vielleicht habt ihr ja noch Tipps wie man am Besten mit den Punkten für die Frames als Datenstruktur umgeht, wie man sie schnell bearbeiten Transformieren kann usw. Trapezkorrektur usw. Es ist ja keine Matrix in dem Sinne weil ich nur die Punkte definiere die ich auch setzen möchte.
Ein Array mit 4096x4096 definierten Punkten ist sicherlich auch nicht besonders performant.

Habt ihr weitere Ideen welche Spiele man schön umsetzen könnte?
SuperMarioBros wär noch der Kracher ;) Aber komme eher aus einer anderen Ecke der Programmierung (Socketanwendungen, Netzwerklastgenerierung, Protokolle höherer Schichten umsetzen [SIP z.B.], ...) Hätte spontan keine Ahnung wie man das sauber umsetzt.

Code: Select all

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace LaserTTT
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Point
    {
        public ushort x;    // 2 bytes, value: 0-4095 (x-coordinate)
        public ushort y;    // 2 bytes, value: 0-4095 (y-coordinate)
        public byte r;    // 1 byte, value: 0-255 (red)
        public byte g;    // 1 byte, value: 0-255 (green)
        public byte b;    // 1 byte, value: 0-255 (blue)
        public byte i;    // 1 byte, value: 0-255 (intensity)
    };

    public partial class Form1 : Form
    {
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseGetCardNum")]
        public static extern int EasyLaseGetCardNum();
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseWriteFrame")]
        public static extern byte EasyLaseWriteFrame(ref int cardNumber, Point [] datapointer, int bytecount, ushort speed);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseStop")]
        public static extern bool EasyLaseStop(ref int cardNumber);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseClose")]
        public static extern bool EasyLaseClose();
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseGetLastError")]
        public static extern int EasyLaseGetLastError(ref int CardNumber);
        [DllImport("easylase.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "EasyLaseGetStatus")]
        public static extern int EasyLaseGetStatus(ref int CardNumber);
        

        private int easylaseCount;
        private int card = 0;

        public Form1()
        {
            InitializeComponent();            
        }

        private void Form_Closing(object sender, EventArgs e)
        {
            if (easylaseCount > 0)
            {
                EasyLaseStop(ref card);
                EasyLaseClose();
            }
        }

        private unsafe void button1_Click(object sender, EventArgs e)
        {
            easylaseCount = EasyLaseGetCardNum();
            MessageBox.Show(Convert.ToString(EasyLaseGetStatus(ref card)));
            if (easylaseCount > 0)
            {

                Point[] pointarray = new Point[15];
                ushort x = 2000;
                ushort y = 2000;
                byte r = 0;
                byte g = 255;
                byte b = 0;
                byte intens = 0;

                for (int i = 0; i < 15; i++)
                {
                    pointarray[i].x = x;
                    pointarray[i].y = y;
                    pointarray[i].r = r;
                    pointarray[i].g = g;
                    pointarray[i].b = b;
                    pointarray[i].i = intens;
                    x += 30;
                    //y += 30;
                }
                try
                {
                    EasyLaseWriteFrame(ref card, pointarray, Marshal.SizeOf(typeof(Point)) * pointarray.Length, 500);
                }
                catch (AccessViolationException ave)
                {
                    
                    MessageBox.Show(ave.Message);
                }
            }
        }
    }
}