Hilfe bei Easylase.dll und C#

Allgemeine Fragen zu Lasershow Software und Show-Programmierung.
Post Reply
User avatar
jokakilla
Posts: 36
Joined: Thu 07 Aug, 2003 5:05 pm
Location: Braunschweig
Contact:

Hilfe bei Easylase.dll und C#

Post by jokakilla » Thu 06 Mar, 2008 9:18 am

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}};

User avatar
jojo
Posts: 1939
Joined: Fri 21 Dec, 2001 12:00 pm
Do you already have Laser-Equipment?: -
Location: Germany
Contact:

Post by jojo » Thu 06 Mar, 2008 9:54 am

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

User avatar
jokakilla
Posts: 36
Joined: Thu 07 Aug, 2003 5:05 pm
Location: Braunschweig
Contact:

Post by jokakilla » Thu 06 Mar, 2008 10:12 am

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.

User avatar
afrob
Posts: 997
Joined: Mon 05 Aug, 2002 12:00 pm
Do you already have Laser-Equipment?: RayComposer NET und RayComposer USB
Location: Frankfurt am Main, Germany
Contact:

Post by afrob » Thu 06 Mar, 2008 1:01 pm

[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

User avatar
jojo
Posts: 1939
Joined: Fri 21 Dec, 2001 12:00 pm
Do you already have Laser-Equipment?: -
Location: Germany
Contact:

Post by jojo » Thu 06 Mar, 2008 4:39 pm

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

User avatar
thomasf
Posts: 1262
Joined: Sun 06 Oct, 2002 12:00 pm
Do you already have Laser-Equipment?: YES
Location: Berlin
Contact:

Post by thomasf » Thu 06 Mar, 2008 5:23 pm

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

User avatar
jokakilla
Posts: 36
Joined: Thu 07 Aug, 2003 5:05 pm
Location: Braunschweig
Contact:

Post by jokakilla » Thu 06 Mar, 2008 6:05 pm

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();
            }
        }
    }
}
Last edited by jokakilla on Thu 06 Mar, 2008 7:25 pm, edited 1 time in total.

User avatar
jokakilla
Posts: 36
Joined: Thu 07 Aug, 2003 5:05 pm
Location: Braunschweig
Contact:

Post by jokakilla » Thu 06 Mar, 2008 7:20 pm

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.

User avatar
jokakilla
Posts: 36
Joined: Thu 07 Aug, 2003 5:05 pm
Location: Braunschweig
Contact:

Post by jokakilla » Tue 11 Mar, 2008 4:18 pm

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);
                }
            }
        }
    }
}

Post Reply

Return to “Software & Programmierung”

Who is online

Users browsing this forum: No registered users and 2 guests