none
Extern C Funktion aus DLL mit Visual Basic asychron starten RRS feed

  • Frage

  • Hallo,

    ich habe eine DLL mit C++ programmiert mit zwei extern "C" Funktionen. Die erste funktioniert einwandfrei. Die zweite Funktion benötigt jedoch eine Eingabe die ich über eine TextBox in Visual Basic einlesen und mit einem Button-klick in den vorher übergebenen Puffer schreiben wollte. Da ich vermutet habe dass VB auf das Durchlaufen der Funktion wartet wollte ich das ganze in einem asynchronen Thread starten und nach starten mit return zurück zu VB springen. Allerdings wartet meine VB-Anwendung anscheinend trotzdem noch und die Funktion in der DLL wartet auf rdy==1. Wenn ich die Eingabe vor dem Starten der Funktion mache und sofort die Variable rdy auf 1 setze funktioniert alles. Aber eigentlich wäre mir lieber wenn die Funktion erst gestartet wird und die Eingabe erst erfragt wenn eine Verbindung zum Server aufgebaut wurde. Weiß vielleicht jemand wie ich das realisieren könnte und wieso mein erster Versuch nicht funktioniert hat?

    Code von der 2. Funktion:

    extern "C" __declspec(dllexport) int __stdcall ssh_test_thread(int *rdy, int *status, char *pw, int *drucker)
    {
    //Starten ssh_test asynchron
    	auto t= std::async(std::launch::async, ssh_test, rdy, status, pw, drucker);
    	return 1; //Gibt 1 an die VB-Anwendung zurück
    }
    
    int ssh_test(int *rdy, int *status, char *pw, int *drucker)
    {
    	ssh_session my_ssh_session;
    	int rc;
    	string password;
    	// SSH Session öffnen
    	my_ssh_session = ssh_new();
    	if (my_ssh_session == NULL)
    		return(-1);
    	ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "10.0.0.1");
    	// Zum Server verbinden
    	rc = ssh_connect(my_ssh_session);
    	if (rc != SSH_OK)
    	{
    		*status = -1;
    		return(-1);
    	}
    
    	if (verify_knownhost(my_ssh_session) < 0)
    	{
    		ssh_disconnect(my_ssh_session);
    		ssh_free(my_ssh_session);
    		*status = -2;
    		return(-2);
    	}
    
    	char c;
    	password = "";
    	*status = 1;
    	while (*rdy!=1) //Hier wartet er auf die Eingabebestätigung
    	{
    		Sleep(100);
    	}
    	password = pw;
    	rc = ssh_userauth_password(my_ssh_session, "root", password.c_str());
    	if (rc != SSH_AUTH_SUCCESS)
    	{
    		*status = -3;
    		ssh_disconnect(my_ssh_session);
    		ssh_free(my_ssh_session);
    		return(-3);
    	}
    
    	
    
    ... //Hier werden weitere SSH Befehle ausgeführt
    	return 1;
    }

    Module Module1
    
    'Die Variablen, die an die Funktionen übergeben werden
        Public i, j As Int32
        Public passwort(256) As Byte
        Public rdy, status, drucker As Int32
    
    'Die Funktionen aus der DLL
        Public Declare Sub verbindungpruefen Lib "test.dll" Alias "_verbindungpruefen@8" (ByRef inet As Int32, ByRef server As Int32)
        Public Declare Function ssh_test Lib "test.dll" Alias "_ssh_test_thread@16" (ByRef rdy As Int32, ByRef status As Int32, ByVal pw As Byte(), ByRef drucker As Int32) As Int32
    
    End Module

    Vielen Dank, Chris





    • Bearbeitet DerChris88 Dienstag, 24. Mai 2016 14:29
    Dienstag, 24. Mai 2016 14:19

Antworten

Alle Antworten

  • Hallo Chris,

    so einfach funktioniert das nicht, denn .NET Delegates sind typsicher und auch ansonsten auf Sicherheit ausgelegt. Siehe dazu: How to: Marshal Callbacks and Delegates By Using C++ Interop. Zum anderen ist std:async was anderes als .NET async / await für C++.

    Eine Alternative mag bei Dir sein, das Ganze in C++/CLI zu implementieren und das als Assembly einzubinden, siehe How to: Define and Use Delegates (C++/CLI).

    Wobei es auf der anderen Seite für SSH .NET Bibliotheken gibt, z. B.:

    SSH.NET Library

    oder NuGet: SSH.NET.

    was Aufwand und Risiko minimieren kann.

    Gruß Elmar

    • Als Antwort markiert DerChris88 Donnerstag, 26. Mai 2016 21:04
    Mittwoch, 25. Mai 2016 11:47
  • Hallo Elmar,

    vielen Dank für die Antwort. Bei der ganzen Sache handelt es sich eigentlich nur um einen Test inwiefern eine C++ Konsolenanwendung zu einer DLL geändert und ihr mit VB eine GUI gegeben werden kann. Sicher wäre es einfacher und auch sicherer eine .NET Bibliothek zu benutzen und das ganze in VB zu programmieren oder eine GUI mit C++ und winapi zu programmieren, aber ich wollte es einfach mal versuchen.

    Das Blockieren habe ich jetzt mit async / await auf VB Seite gelöst. Soweit funktioniert es jetzt, auch wenn es etwas unschön ist das Passwort in einen öffentlichen Datenpuffer zu schreiben aber ist wie gesagt nur ein Test, werde aber Deine weiteren Vorschläge zu Marshal Delegates und CLI auch noch ausprobieren.

    Gruß, Chris



    • Bearbeitet DerChris88 Freitag, 27. Mai 2016 10:25
    Donnerstag, 26. Mai 2016 21:04