| 

.NET C# Java Javascript Exception

3
Hallo,

ich schreibe gerade an einer Arbeit zur Steuerung einer Achse, die in einer vorgegebenen C# GUI angerufen werden soll. Die Achse lässt sich nur mit C++ programmieren und mit der Achse klappt es schon alles wunderbar. In C# bin ich ein Newbie.

Von C# kann ich keine Verbindung zur Achse aufbauen. Wie kann ich dies am besten realisieren?

Die Achse lässt sich mit dem folgenden Code aufrufen:
C++
Controller->connect(port, baudrate);


Bin für jede Hilfe und Tipp sehr dankbar.

Gruß

maxS
News:
13.01.2012
maxS 11 1 2
1
Hm, könnte man nicht 'einfach' eine Funktion in die c++ assembly implementieren die sich über c# aufrufen lässt? Also ich glaube es wäre am einfachsten wenn du alles in c++ lässt und die c++ DLL mit c# aufrufst.
Nicolai Schönberg 13.01.2012
4 Antworten
1
Wie stellst Du denn in C++ die "Verbindung" her? Hast Du da eine DLL des Herstellers, die Du einbinden must? Falls ja, warum nicht die DLL in C# einbinden und einen Adapter dafür schreiben?

Stichwort: http://msdn.microsoft.com/de-de/library/system.runtime.interopservices.dllimportattribute.aspx
13.01.2012
Xantiva 2,3k 2 9
1
Wenn ich dein Problem richtig verstehe, dann könntest du es so lösen:
Mache dir ein Wrapper-Routine mit einer pointer-Rückgabe in deinem C++ code, z.B.

CLStep* CLStep_Create() { return new CLStep(); }
void CLStep_ConnectSimple(CLStep* pCLStep, int no, int port, int baud, bool bval) {CLStep->ConnectSimple(no, port, baud, bval); }


Der dllimport im C# code ist dann:

[DllImport("LStep.dll")]
public static extern IntPtr CLStep_Create();

[DllImport("LStep.dll")]
public static extern void CLStep_ConnectSimple(IntPtr value, int no, int port, int baud, bool bval);


So oder so ähnlich, musst mal ausprobieren, ist jetzt ungetestet!
13.01.2012
Eiger 1,9k 2 9
Um die Antwort von Eiger noch ein klein wenig zu erweitern: Wie genau das dann in C++ und in C# jeweils auszusehen hat, ist hier recht gut beschrieben: http://www.codeproject.com/KB/cs/unmanage.aspx
Karill Endusa 16.01.2012
1
Wie schon in mehreren Posts genannt, kannst Du versuchen, das Problem mit P/Invoke anzugehen. Dabei hantierst Du de facto jedoch mit statischen Funktionsaufrufen. Da Du aber offenbar ein Objekt (eine Instanz von CLStep) erzeugen und Methoden auf dieser Instanz aufrufen mußt, geht das nicht ganz ohne Schwierigkeiten. Du brauchst dafür eine Wrapper-Schicht - z.B. in der Art, wie sie Eiger vorgeschlagen hat, oder auch, in dem Du in C++ einen Singleton baust, der die CLStep-Instanz wrappt, sowie Funktionen, die auf Methodenaufrufe auf diesem Singleton delegieren.

Eine Alternative wäre aber auch, C++/CLI zu nutzen, auch bekannt als Managed C++. Dann wäre der Ansatz, in C++ ein .NET-Objekt zu definieren, das als Wrapper bzw. Proxy für CLStep agiert. Diesen Wrapper könntest Du dann aus C# heraus wie ein normales .NET-Objekt benutzen. Diesen Ansatz würde ich hier favorisieren, denn offenbar folgt Deine Steuerungs-API ja dem objektorientierten Paradigma, und so mußt Du nicht aus diesem Paradigma ausbrechen, um von managed nach unmanaged zu kommen.
16.01.2012
Matthias Hlawatsch 13,2k 4 9
0
Hallo,

danke für die Hilfe.

ich möchte gerne den Ansatz mit dem C++/CLI-Wrapper, aber ich habe so meine Probleme mit dem CLStep-Objekt. Ich weiss nicht was an dem Wrapper nicht richtig, deshalb folgt jetzt mein Code.

Dieser soll den Code für die Steuerung aufnehmen.
//NativeCPP.h
#pragma once
#pragma unmanaged
#include <stdint.h>
#include "LStep.h"
using namespace std;

class NativeCPP
{
public:
NativeCPP(void) {
LS = CLStep();
};
~NativeCPP(void) {};

CLStep getData(void)
{
return LS;
};

uint32_t connect(void)
{
int n = LS.ConnectSimple(1, "COM4", 9600, true);
return n;
};

private:
CLStep LS;
};


Jetzt folgt der eigentliche Wrapper
// CPPLibrary.h
#pragma once
#include <stdint.h>
#include "NativeCPP.h"
#include "LStep.h"
using namespace std;

#pragma managed

namespace CPPLibrary {
public ref class ManagedCPPWrapper
{
public:
ManagedCPPWrapper(void);
~ManagedCPPWrapper(void);

// Functions we are wrapping from the native code
CLStep getData();
uint32_t connectAxis();

private:
NativeCPP* NATIVE;
};
}


//CPPLibrary.cpp
#include "stdafx.h"
#include "CPPLibrary.h"
#include "LStep.h"
using namespace CPPLibrary;

ManagedCPPWrapper::ManagedCPPWrapper(void)
{
this->NATIVE = new NativeCPP();
};

ManagedCPPWrapper::~ManagedCPPWrapper(void)
{
delete this->NATIVE;
};

CStep4 ManagedCPPWrapper::getData()
{
CLStep origArr = this->NATIVE->getData();
return origArr;
};

uint32_t ManagedCPPWrapper::connectAxis()
{
return this->NATIVE->connect();
};


Bin für jede Hilfe oder Tipp sehr dankbar. Ein Beispiel wäre für mich sehr hilfreich.


> Hallo,
>
> danke für den Hinweise.
>
> Ja von dem Hersteller habe ich eine dll.
>
> Mir ist aber nicht klar, wie ich ein dllImport mit einem Objekt/Konstruktor mache. Ein Beispiel wäre mir sehr hilfreich.
>
> Vielleicht war meine vorherige Angabe zu ungenau, in C++ muss die Deklaration folgendermaßen sein:
#include "LStep.h"

...
CLStep LS;
LS.ConnectSimple(1, port, baudrate, true);
...
13.01.2012
maxS 11 1 2
maxS 11 1 2

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH