Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von Spook
Thema: [erledigt] Wie übersetze ich das Feld "char szAccess[2]" aus einer C++ lib in C#?
Am im Forum: Rund um die Programmierung

Hallo,

du könntest es als byte[] definieren und mit mit dem MarshalAs Attribut in Kombination mit UnmanagedType.ByValArray und SizeConst=2 versehen.

Grüße
spooky

PS: char aus C++ ist in .NET byte.

Thema: Ablauf/ Struktur einer Echtzeit Anwendung (hier 33ms ) Bildschirm Darstellungsproblem
Am im Forum: Rund um die Programmierung

Hallo luciluke,

du könntest dir folgende Dinge anschauen:

Multimedia Timer Dieser bietet eine bessere Auflösung als die im Framework vorhandenen Timer (~1ms).

Zusätzlich kann der GC selbst die Anwendung anhalten, was zu Rucklern führt. Ganz besonders bei full blocking collections. Möglichweise das was du als Ungleichmäßig beschreibst. Dort kann dir möglichweise die Verwendung von SustainedLowLatency weiterhelfen.

Du kannst auch die Auflösung des Windows Schedulers selbst erhöhen, so dass dieser nicht bei ~15ms liegst sondern bei 0.5ms. NtSetTimerResolution
NtQueryTimerResolution
NtSetTimerResolution

Grüße
spooky

Thema: Fakultät von Int wird bei 22 negativ, dann wieder positiv
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

22! viel größer als Int32.MaxValue (2^31-1)
Daher hast du Überläufe vom Positiven ins Negative und wieder zurück.

Mit BigInteger sollte es gehen.

Thema: Assembly zu eigener Assembly hinzufügen, die einen starken Namen hat
Am im Forum: Rund um die Programmierung

Die Datei muss nicht eingebettet werden. Diese kann einfach nachträglich signiert werden.

Thema: Assembly zu eigener Assembly hinzufügen, die einen starken Namen hat
Am im Forum: Rund um die Programmierung

http://www.blackwasp.co.uk/ILMergeSigned.aspx (Abschnitt "Signing Without Merging")
http://www.microsoft.com/en-us/download/details.aspx?id=17630 (Download ILMerge)

Thema: Zugriff von 64-Bit auf 32-Bit Dll, Elegantere lösung als über 32-Bit COM?
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo,

wenn du native DLLs als Abhängigkeiten hast, dann macht es keinen Sinn AnyCPU zu verwenden, außer du lädst diese dynamisch, so dass beide Architekturen funktionieren.
Die meisten Bibliotheken, werden als AnyCPU vorliegen, da diese eben keine nativen Abhängigkeiten haben und damit von x86 und x64 Anwendungen verwendet werden können. Das ist gerade das tolle, dass du eine reine .NET Anwendung eben nicht fix auf eine Architektur kompilieren musst.

Wenn dies nicht der Fall ist, dann kompiliere entweder als x86 oder als x64. Bei uns ist dies nur bei der .exe der Fall, da diese entscheident ist. Alle (.NET) DLLs sind AnyCPU.


Grüße
spooky

Thema: Windows service, Setup Prozess nach Setup Prozess starten.
Am im Forum: Netzwerktechnologien

Hallo,

du kannst mit der WaitForSingleObject Funktion warten, bis ein Prozess beendet wurde. Diese mit dem hProcess-Handle deines procInfo out-Parameters und dem passenden Timeout (vermutlich INFINITY 0xFFFFFFFF als uint oder -1 als int) aufrufen.

Alternativ kannst du auch mit der Process-Klasse (und dem dwProcessId-Member) arbeiten:

Process.GetProcessById((int)info.dwProcessId).WaitForExit();


Grüße
spooky

Thema: Universal App: Bitmap in Gridview binden ohne Referenz auf physische Datei
Am im Forum: GUI: WPF und XAML

Hallo ChristophF,

ich würde die Datei in einen MemoryStream kopieren und diesen zum Laden verwenden, da die Datei dann nicht geöffnet bleibt.
Am einfachsten ist es die Datei als Stream zu öffnen und mit CopyTo in den MemoryStream zu kopieren.
Danach die Position des MemoryStreams wieder auf 0 setzen und dann zum Laden des Bildes vewenden (den danach FileStream natürlich mit Close oder Dispose schließen).

Grüße
spooky

Thema: volatile und Multithreading - Race bei i += 7
Am im Forum: Rund um die Programmierung

In deinem Verlinkten Artikel steht ebenfalls:

Zitat
Die C# ECMA-Spezifikation garantiert, dass die folgenden Typen atomar geschrieben werden: Verweistypen, „bool“, „char“, „byte“, „sbyte“, „short“, „ushort“, „uint“, „int“ und „float“.

Ich vermute dass 64bit Datentypen in einem 64bit Prozess ebenfalls atomar geschrieben werden können.

Thema: volatile und Multithreading - Race bei i += 7
Am im Forum: Rund um die Programmierung

Hallo gunnag,

Zitat von gunnag
das Schlüsselwort volatile gibt mir eine acquire und release semantic (also keinen full-fence).

Das volatile Schlüsselwort bewirkt, dass der Inhalt nicht gecacht, sondern bei jedem (lesenden) Zugriff neu aus dem Speicher in ein Register kopiert wird.

Eine genauere Beschreibung findest du hier:
volatile (C#-Referenz)

Ich frage mich eher, ob die Variable als volatile deklariert werden muss. Dies ist in diesem Fall vermutlich unsinnig, da der Property-getter die Variable eh nicht cachen kann und frisch aus dem Speicher auslesen muss. Solange nur Thread 2 die Variable ändert, kannst du volatile weglassen.

Grüße
spooky

Thema: Bei 2 o. 3 Screens den Inhalt in ein Fenster "Clonen"
Am im Forum: Grafik und Sound

Diese Methode sollte dir weiterhelfen:
Graphics.CopyFromScreen

Um die Bildschirme auszumessen, kannst du die Screen-Klasse verwenden.

Grüße
Spooky

Thema: Access Violation bei TCL-Kommandoaufruf über DLL
Am im Forum: Rund um die Programmierung

Hallo,

kannst du bitte die originale Definition der Methodensignatur (C/C++) posten?

spooky

Thema: Access Violation bei TCL-Kommandoaufruf über DLL
Am im Forum: Rund um die Programmierung

Hallo dls,

versuche mal die korrekte Calling-Convention für den Tcl_ObjCmdProc Delegaten zu setzen:
UnmanagedFunctionPointerAttribute

Grüße
spooky

Thema: Generischer Vergleich 2er Objekte
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo elTorito,

ich würde Project das Interface IComparable<Project> implementieren lassen (Implementierung deines Comparers).
Danach kannst du aus


public int BinarySearch(T item, IComparer<T> comparer)
        {
            List<T> itemsList = (List<T>)this.Items;
            return itemsList.BinarySearch(item, comparer);
        }


public int BinarySearch(T item)
        {
            List<T> itemsList = (List<T>)this.Items;
            return itemsList.BinarySearch(item);
        }

machen und es sollte automatisch deine Implementierung für die binäre Suche verwendet werden.
Ich hoffe das ist was du suchst.

Grüße
spooky

Thema: Remote Shutdown im Netzwerk möglich?
Am im Forum: Netzwerktechnologien

Hallo KEFHVDI,

dein finaler String für die Argumente enthält nur einen Backslash. Entweder die Backslashes ganz weglassen oder du musst vier nehmen.

Grüße
spooky

Thema: Geschützer Speicher Fehler bei Aufruf einer Nativen DLL mit string Pointer
Am im Forum: Rund um die Programmierung

Hallo Crash129,

dieser Code sollte dir weiterhelfen:


    class Program
    {
        static void Main(string[] args)
        {
            string name = API.GetServerName();
            Console.WriteLine("Servername is {0}.", name);
        }
    }

    public static class API
    {
        [DllImport("API.dll", EntryPoint = "GetServerName", CallingConvention = CallingConvention.Cdecl)]
        private static extern int GetServerName(ref IntPtr buffer);

        public static string GetServerName()
        {
            IntPtr buffer = Marshal.AllocHGlobal(1024);
            try
            {
                int returnCode = GetServerName(ref buffer);
                // Mögliche Fehlerbehandlung
                // if (returnCode < 0)
                //    throw new Exception();
                return Marshal.PtrToStringAnsi(buffer);
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
    }

Die Methode gibt bei mir das erwartete "Unbekannt" zurück, siehe original Code:
int SAMP::API_GetServerIP(char *&serverip) {
	char ip[15] = { "Unbekannt" };
	if (_Memory.CheckHandles() == 1) {
		_Memory.Read((DWORD*)(_Memory.GetSAMPBaseAddress() + SAMP_SERVERIP_ADDR), &ip, sizeof(ip));
	}
	memcpy(serverip, ip, sizeof(ip));
	return _Memory.CheckHandlesErrorCode;
}

Ein Wrapper bringt hier glaube ich nur einen unnötigen Mehraufwand. Wenn die API nur reine C++ Klassen exportieren würde, dann müsste man den Weg über eine CLI-DLL gehen, aber wegen drei Methoden halte ich dies für etwas übertrieben.

Grüße
Spooky

Thema: Durchreichen von Referenzen nach C++ DLL über eine managed C++ Schicht
Am im Forum: Rund um die Programmierung

Bei mir waren beide Funktionen im gleichen (C++/CLI) Projekt.
Ich konnte deinen Fehler nachstellen, und auch beide Lösungen haben funktioniert.

Kannst du mal deine Wrapper-Methode umbennen, so dass nicht beide den gleichen Namen haben. Vielleicht ist dies ein Teil des Problems.

Grüße

Thema: Durchreichen von Referenzen nach C++ DLL über eine managed C++ Schicht
Am im Forum: Rund um die Programmierung

Hallo Almeida,

die Typen scheinen wohl nicht kompatibel zu sein.
Du kannst dies aber so lösen:


short getParameters(bool% isA, bool% isB, bool% isC)
{
	bool a = isA;
	bool b = isB;
	bool c = isC;
	short result = nativeDll::getParameters(a, b, c);
	isA = a;
	isB = b;
	isC = c;
	return result;
}

Edit:

Wenn du es in einer Zeile machen möchtest, kannst du die Kompatibilität auch erzwingen:
short getParameters(bool% isA, bool% isB, bool% isC)
{
	return ((short(_cdecl*)(bool%, bool%, bool%))&nativeDll::getParameters)(isA, isB, isC);
}

Dabei aber die korrekte Calling Convention der nativen Funktion verwenden.

Grüße
spooky

Thema: Child Process ID von mstsc abfragen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo logan517,

wie herbivore geschrieben hat liegt es daran, dass die Anwendung sich selbst nocheinmal startet (habe ich an meinem Rechner getestet).
Dies hättest du leicht mit Refresh und HasExited herausfinden können.

Das hier sollte dir weiterhelfen:
Unterprozess finden

Hallo Abt,

die Process Klasse cacht die Prozess-ID intern, daher bringt der Code leider nicht so viel


Grüße
spooky

Thema: serielle Schnittstelle einlesen - unterschiedliche Anzahl von Zeichen
Am im Forum: Rund um die Programmierung

Hallo MailoKooiker,

erzeuge ein Byte-Array mit der genwünschten Größe und fülle dieses mit Hilfe der Stream.Read Methode in einer while-Schleife so lange, bis dieses komplett gefüllt ist (die Methode muss nicht die angeforderte Anzahl liefern) oder Read den Wert 0 zurück gibt (dein Fehlerfall).
Dabei musst du offset und count nach jedem Durchlauf anpassen.

Grüße
spooky

Thema: C - void-Pointer mit Typ-Größe auslesen
Am im Forum: Rund um die Programmierung

Wenn du den Zeiger und die Größe hast, sollte es so gehen:

VOID SetArrayElement(LPVOID dst, SIZE_T elementSize, INT index, LPVOID src)
{
	memcpy((LPBYTE)dst + (index * elementSize), src, elementSize);
}

Grüße
spooky

Thema: [gelöst] DllImport: Array mit bestimmter Größe in Funktions-Deklaration?
Am im Forum: Rund um die Programmierung

Zwei Möglichkeiten:
Unterschiedliche CallConv zwischen C++/C#.
Du speicherst den Delegaten nicht, wie es weismat dir geraten hat.

Bei mir funktioniert der Code, siehe angehängtes Projekt.
Nun sollte es doch möglich sein, den Fehler zu finden ...


Grüße
spooky

Thema: [gelöst] DllImport: Array mit bestimmter Größe in Funktions-Deklaration?
Am im Forum: Rund um die Programmierung

Mein Vorschlag wäre Folgender:

Erstelle in C++ eine Struct mit 3 Werten und verwende diese anstatt eines mehrdimensionalen Arrays. Zusätzlich solltest du die Aufrufkonvention für die Callback-Funktion angeben (WINCC):

struct PositionData
{
	double v0;
	double v1;
	double v2;
};

typedef void (WINCC* FPS_PositionCallback) ( unsigned int   devNo,
                                        unsigned int   length,
                                        unsigned int   index,
					PositionData * positions);

Der 'length' Parameter gibt die Länge des Arrays an.

In C# definierst du die Struct nochmal genau so und änderst Definition der Callback-Methode:

public struct Positions
{
    public double v0;
    public double v1;
    public double v2;
}

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public unsafe delegate void FPS_PositionCallback(uint devNo, uint length, uint index, Positions* position);

[DllImport("TestDll.dll")]
public static extern int setPositionCallback(uint devNo, FPS_PositionCallback callback, uint lbSmpTime);

Damit sollte es funktionieren.

Solltest du kein Unsafe verwenden wollen, so kannst du im C# den Parameter auch als IntPtr definieren und so verwenden:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void FPS_PositionCallback(uint devNo, uint length, uint index, IntPtr position);

[DllImport("TestDll.dll")]
public static extern int setPositionCallback(uint devNo, FPS_PositionCallback callback, uint lbSmpTime);

static void Test(uint devNo, uint length, uint index, IntPtr position)
{
    // Speicher anlegen
    double[] data = new double[length * 3];
    // Daten in C# Array kopieren
    Marshal.Copy(position, data, 0, data.Length);

    // Was tolles machen
    for (int i = 0; i < data.Length; i++)
    {
        data[i] = i;
    }

    // Daten zurück kopieren
    Marshal.Copy(data, 0, position, data.Length);
}


Grüße
spooky

Thema: [gelöst] DllImport: Array mit bestimmter Größe in Funktions-Deklaration?
Am im Forum: Rund um die Programmierung

Warum definierst du nicht das Array als ganz simples eindimensionales Array (double*) mit der Länge (n*3). Damit ist das Marshalling super einfach. Dann kannst du den Parmater als IntPtr definieren, in ein C# Array kopieren und nach der Bearbeitung wieder zurück (falls nötig).

In einem C++ Projekt (ich gehe davon aus, dass du die C++ Dll geschrieben hast) ist die Standard Aufrufkonvention cdecl. Dies kannst du global im Projekt umstellen (da du nicht weisst was dies ist, gehe ich davon aus, dass du es nicht gemacht hast). Ansonsten kannst du für jede Methode einzeln die Konvention festlegen.

Poste doch bitte die komplette .h Datei welche die exportierten Methoden beinhaltet. Normalerweise heisst diese <Projektname>.h

Für dich zum Nachlesen:
Aufrufkonvention


Grüße
spooky

Thema: Lebensdauer eines Objekts das nur durch einen Delegaten referenziert wird
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Hallo chilic,

die Referenz auf das Objekt wird in dem dabei erzeugten Delegate mit gespeichert.
Der Delegate enthält immer eine Referenz auf die aufzurufene Methode. Ist die Methode nicht statisch, so enthält er zusätzlich noch das Objekt für welches die Methode aufgerufen werden soll.

Grüße
spooky

Thema: Aktualisierung einer Grafik in WPF
Am im Forum: GUI: WPF und XAML

Hallo,

die GUI wird erst aktualisiert, wenn deine methode "StartAnimation" zurückkehrt. Anstall mit Sleep zu warten, muss du diese zyklisch aufrufen, z.B. mit Hilfe eines Timers (der alle 500ms) ausgelöst wird.

Grüße

Thema: Änderung an ObservableCollection-Items mitbekommen
Am im Forum: Basistechnologien und allgemeine .NET-Klassen

Wenn du Änderungen der einzelnen Objekte mitbekommen möchstes muss der Typ der Collection INotifyPropertyChanged implementieren.

Thema: Colorbar mit WPF
Am im Forum: GUI: WPF und XAML

Hallo,

die, meiner Meinung, einfachste Art ist es, das Darstellen der Colorbar und das Zeichnen des Bildes mit der gleichen Farbpalette zu machen (siehe BitmapPalette).
Diese kann dann beliebige Farbübergänge haben.

Den Slider kannst du dann auch relativ einfach zeichnen:
Du nimmst ein Bild mit 1x256 oder 256x1 Pixel mit den Werten 0..255 und wendest auf das Bild deine vorhandene Palette an. Dieses Bild kannst du dann direkt zeichenen oder dynamisch in ein Image einsetzten.

Grüße spooky

Thema: Usb-Stream bzw. Handle wird nicht (richtig) geschlossen: SafefileHandle is invalid beim Neuöffnen
Am im Forum: Rund um die Programmierung

Hallo,

beide Close() Methoden rufen intern Dispose auf. Den Finally-Block kannst du damit weglassen.

Grüße

Thema: byte[] gefüllt mit 0len
Am im Forum: Datentechnologien

Hallo Endro,

ich rate einfach mal:

db.Read())
byte[] buffer = new byte[db.GetBytes(1, 0, null, 0, int.MaxValue)];
db.GetBytes(1, 0, buffer, 0, buffer.Length);
List.Add(new FileModel
                        {
                            Name = db.GetValue(0).ToString(),
                           File = buffer
                     });

Grüße
spooky