Anfänger Frage
-
Hallo, ich arbeite Heute zum ersten mal mit c++. Normalerweise programmiere ich in C#.
da ich nun ein Dll erstellen muss die in C# benutzen kann stehe ich etwas auf dem Schlauch.
ich habe mir in C++ eine Klasse angelegt und will nun auf eine Methode zugereifen.
leider wird mir die Methode nicht angeboten, obwohl diese Public ist.
Headerdatei:
#pragma once using namespace System; namespace NTVOrientationGPIO_Dll { public class GPIO { public: GPIO(void); bool FindGPIOs(); }; }
C++ Datei:
#include "stdafx.h" #include <windows.h> #include "NTVOrientationGPIO_Dll.h" #include <stdio.h> #include <tchar.h> #include "Oak.h" NTVOrientationGPIO_Dll::GPIO::GPIO() { } bool NTVOrientationGPIO_Dll::GPIO::FindGPIOs() { bool success; tOakSensor Sensor; success = Oak_FindSensor(0x0013, 0x0000, NULL, NULL, NULL, NULL, NULL, &Sensor); return success; }
Die Methode bool FindGPIOs(); müsste doch nun eigentlich ansprechbar sein!?!?!
Es wäre super wenn ihr helfen könntet!
-
OK... ich hab den Fehler gefunden... allerding zieht er ein weiteren Fehler nach sich.
Code:
public class GPIO sealed { public: GPIO(void); void test(); bool FindGPIOs(); private: };
muss in:
public ref class GPIO sealed { public: GPIO(void); void test(); bool FindGPIOs(); private: };
geändert werden.
nun kommt folgende fehlermeldung beim Compilieren.
Fehler 1 error C3821: "bool NTVOrientationGPIO_Dll::GPIO::FindGPIOs(void)": Ein verwalteter Typ oder eine verwaltete Funktion kann nicht in einer nicht verwalteten Funktion verwendet werden. e:\CPPWorkspace\NTVOrientationGPIO_Dll\NTVOrientationGPIO_Dll\NTVOrientationGPIO_Dll.cpp 22
Fehler 2 error C3645: "NTVOrientationGPIO_Dll::GPIO::FindGPIOs": __clrcall kann nicht für Funktionen verwendet werden, die als systemeigener Code kompiliert werden. e:\cppworkspace\ntvorientationgpio_dll\ntvvorientationgpio_dll\NTVOrientationGPIO_Dll.h 12
wenn ich die Methode
bool FindGPIOs();
auskommentiere bekomme ich diesen Fehler nicht.
In dieser Methode rufe ich eine Methode auf die in einer Externen DLL ist.
-
Du bringst da einiges durcheinander und mischst natives C++ und C++/CLI.
Wenn es wirklich C++ sein soll, sähe es in etwa so aus
#pragma once namespace Foo { class Blubb { public: Blubb(); int f(); }; }
#include "stdafx.h" #include "CppTest.h" Foo::Blubb::Blubb() { } int Foo::Blubb::f() { return 42; } int _tmain(int argc, _TCHAR* argv[]) { Foo::Blubb b; int n = b.f(); return 0; }
Namespace System ist .net, kein C++ und public class, ref und sealed sind auch kein C++, sondern C++/CLI.
-
Hmm... das kann natürlich gut sein..
wie gesagt.. arbeite heute zum ersten mal mit C++Wie genau muss ich denn vorgehen wenn ich am Ende eine Dll, die ich in C# als verweis hizufügen, instanzieren und die Methoden aufrufen kann benötige???
ist eine .NET anwendung.. also wenn ich da kein natives C++ benutze ist das glaube ich nicht schlimm.
-
Also erstmal, was du da machen willst, geht auch in C#. Man kann dort aus DLLs exportierte C-Funktionen aufrufen. Stichwort: PInvoke.
In C++/CLI sieht mein obiger Code nicht so viel anders aus
// CliLibTest.h #pragma once using namespace System; namespace CliLibTest { public ref class Boo { public: Boo(); int f(); }; }
#include "stdafx.h" #include "CliLibTest.h" // Das kann man hier und auch im C++ Beispiel oben auch so schreiben using namespace CliLibTest; Boo::Boo() {} int Boo::f() { return 42; }
Allerdings ist C++/CLI eine der kompliziertesten Programmiersprachen überhaupt, man sollte schon gut C# und C++ können, wenn man das machen will. Es gibt hier übrigens zwei Rubriken tiefer ein eigenes Forum für C++/CLI.
Den leeren Konstruktor habe ich nur als Beispiel hingeschrieben, er würde in C++ und C++/CLI automatisch erzeugt, wenn es keinen anderen Konstruktor gibt.
-
Ich weiss zwar das man in C# einen DLL Import machen kann, aber wenn die die Methode aufrufen will habe ich die Datentypen nicht zur hand;
Aufruf:
[DllImport("oakw.dll", CharSet = CharSet.Auto)] public static extern bool Oak_FindSensor(WORD pid, WORD reference, LPTSTR sn, LPTSTR deviceName, LPTSTR channelName, LPTSTR userDeviceName, LPTSTR userChannelName, LPTSTR userParam, PtOakSensor sensorFound);
das Problem sind jetzt die Datentypen:
WORD, LPTSTR und PtOakSensor. die kennt c# natürlich nicht..der code in der header datei der dll sieht folgendermaßen aus:
#pragma once #include <windows.h> #define VENDOR_ID_TORADEX 0x1B67 #define MAX_NO_CHANNELS 11 #ifdef __cplusplus // If used by C++ code, extern "C" // we need to export the C interface { #endif //--------------------------------------------------------------------------- // differentiate between UNICODE and ASCII versions of the library //--------------------------------------------------------------------------- #ifdef _UNICODE #define tOakString tOakString_w #define tDevicePathString tDevicePathString_w #define tChannel tChannel_w #define tOakSensor tOakSensor_w #define PtOakSensor PtOakSensor_w #define OAK_HANDLE OAK_HANDLE_w #define tNotifyFct tNotifyFct_w #define Oak_Register_Callback Oak_Register_Callback_w #define Oak_Hotplug_Enable Oak_Hotplug_Enable_w #define Oak_NotifyConnectedDevices Oak_NotifyConnectedDevices_w #define Oak_DestroyNotifications Oak_DestroyNotifications_w #define Oak_Feature Oak_Feature_w #define Oak_Initialize Oak_Initialize_w #define Oak_FindSensor Oak_FindSensor_w #define Oak_GetCurrentInReport Oak_GetCurrentInReport_w #define Oak_GetInReport Oak_GetInReport_w #define Oak_SendOutReport Oak_SendOutReport_w #else // ASCII #define tOakString tOakString_a #define tDevicePathString tDevicePathString_a #define tChannel tChannel_a #define tOakSensor tOakSensor_a #define PtOakSensor PtOakSensor_a #define OAK_HANDLE OAK_HANDLE_a #define tNotifyFct tNotifyFct_a #define Oak_Register_Callback Oak_Register_Callback_a #define Oak_Hotplug_Enable Oak_Hotplug_Enable_a #define Oak_NotifyConnectedDevices Oak_NotifyConnectedDevices_a #define Oak_DestroyNotifications Oak_DestroyNotifications_a #define Oak_Feature Oak_Feature_a #define Oak_Initialize Oak_Initialize_a #define Oak_FindSensor Oak_FindSensor_a #define Oak_GetCurrentInReport Oak_GetCurrentInReport_a #define Oak_GetInReport Oak_GetInReport_a #define Oak_SendOutReport Oak_SendOutReport_a #endif //--------------------------------------------------------------------------- #define ALIGN1 __declspec(align(1)) #define ALIGN2 __declspec(align(2)) #define ALIGN4 __declspec(align(4)) #define ALIGN8 __declspec(align(8)) //--------------------------------------------------------------------------- // Type definitions //--------------------------------------------------------------------------- typedef TCHAR tOakString [24]; typedef TCHAR tDevicePathString[256]; // Data that is available about each single data channel. // An array of this type is used as part of the tOakSensor struct below. typedef ALIGN8 struct { ALIGN1 bool IsSigned; ALIGN1 BYTE BitSize; ALIGN1 signed char UnitExponent; ALIGN4 ULONG Unit; ALIGN8 TCHAR UnitStr[24]; ALIGN8 TCHAR ChannelName[24]; ALIGN8 TCHAR UserChannelName[24]; ALIGN8 TCHAR UserChannelName_NV[24]; ALIGN8 BYTE RFU[64]; // reserved for future use } tChannel; // Information that is available about a connected sensor typedef ALIGN8 struct { ALIGN8 TCHAR DevicePath [256]; ALIGN2 WORD VID; ALIGN2 WORD PID; ALIGN2 WORD REV; ALIGN8 TCHAR SN[24]; ALIGN8 BYTE RFU[64]; // reserved for future use ALIGN8 TCHAR DeviceName[24]; ALIGN8 TCHAR UserDeviceName[24]; ALIGN8 TCHAR UserDeviceName_NV[24]; ALIGN8 WORD NumChannels; ALIGN8 tChannel Channel[MAX_NO_CHANNELS]; } tOakSensor; typedef tOakSensor *PtOakSensor, *OAK_HANDLE; // The following line of code defines a type named tNotifyFct. // Functions of this type are needed as Callback functions (see "Oak_Register_Callback" below). // a variable of type tNotifyFct is a pointer to a function that takes a tOakSensor as an argument, and has no return value. // A Callback function must look e.g. like this: // // void __stdcall SensorWasJustAttached(PtOakSensor Sensor, LPARAM UserParam) // { // /* do necessary actions when a sensor was attached / removed */ // } // // IMPORTANT: it is strongly recommended to code the Callback function in a way, that it can be called // more than once for the same sensor! // Given you want to keep a list of connected sensors, verify in the "OnConnect" // function if the sensor is already in the list, before adding it. typedef void (__stdcall * tNotifyFct)(PtOakSensor,LPARAM); //--------------------------------------------------------------------------- // Functions to detect sensors //--------------------------------------------------------------------------- // Register a Notify function that will be called, when a device is connected that matches all the filter parameters // to ignore a filter parameter, set it to 0 or NULL respectively extern "C" __declspec(dllexport) void Oak_Register_Callback( tNotifyFct OnConnect, tNotifyFct OnDisconnect, WORD PID, WORD REV, LPTSTR SN, LPTSTR DeviceName, LPTSTR ChannelName, LPTSTR UserDeviceName, LPTSTR UserChannelName, LPARAM UserParam); // Call once to enable live notifications when a sensor is // inserted or removed extern "C" __declspec(dllexport) void Oak_Hotplug_Enable(void); // Call notify function for all currently connected devices that match the registered filter criteria // (as if all sensors just has been plugged in) extern "C" __declspec(dllexport) void Oak_NotifyConnectedDevices(void); // Clear all callback functions that are registered to be called on Connect/Disconnect of an Oak Sensor device extern "C" __declspec(dllexport) void Oak_DestroyNotifications(void); //--------------------------------------------------------------------------- // Functions to communicate with the sensors //--------------------------------------------------------------------------- // Send and Receive a Feature Report to/from the sensor device // - "RptBuf" will be sent to the sensor. // - The function then waits until the sensor has the result ready ( if there is any). // - "RptBuf" will finally be overwritten by the sensor's answer. extern "C" __declspec(dllexport) bool Oak_Feature (LPTSTR DevicePath, BYTE RptBuf[33], bool ExpectResult); //--------------------------------------------------------------------------- // Functions to Read Sensor values //--------------------------------------------------------------------------- // Toradex recommends to use standard windows functions: // DeviceHandle = Createfile (DevicePath, ...); // ReadFile(DeviceHandle, ReadBuffer, ...); // CloseHandle(DeviceHandle); //--------------------------------------------------------------------------- // Functions only needed for debug purposes //--------------------------------------------------------------------------- // initialize debug stuff extern "C" __declspec(dllexport) void Oak_Initialize(void); //--------------------------------------------------------------------------- // Blocking functions that return directly with a result //--------------------------------------------------------------------------- // Search for a sensor and result a structure containing information about it. // if the provided filters fit for more than one sensor, only one (random) sensor is returned. // The function returns true, if a sensor matched the provided filters. extern "C" __declspec(dllexport) bool Oak_FindSensor( WORD PID, WORD REV, LPTSTR SN, // filters to be set LPTSTR DeviceName, LPTSTR ChannelName, // 0 or NULL acts as wildcard. LPTSTR UserDeviceName, LPTSTR UserChannelName, PtOakSensor SensorFound); // this is the return value // Get current device state (USB communication using Control Endpoint) // - this function only works for Windows Versions XP and higher // - do not use this function to continously read data from the sensor - as it always returns the last // report received, reports may be lost. extern "C" __declspec(dllexport) bool Oak_GetCurrentInReport (LPTSTR DevicePath, BYTE RptBuf[33], BYTE InReportLength); // Wait for a report to be received and return it. // The function returns anyway, after "Timeout_ms" has elapsed. // - do not set the Timeout_ms close to the sensor's report rate. We found that reports may get lost if you do. extern "C" __declspec(dllexport) bool Oak_GetInReport (LPTSTR DevicePath, BYTE RptBuf[33], BYTE InReportLength, WORD Timeout_ms); // Waits for sending a report and sent it. // The function returns anyway, after "Timeout_ms" has elapsed. // - do not set the Timeout_ms close to the sensor's report rate. We found that reports may get lost if you do. extern "C" __declspec(dllexport) bool Oak_SendOutReport (LPTSTR DevicePath, BYTE RptBuf[33], BYTE OutReportLength, WORD Timeout_ms); #ifdef __cplusplus } #endif
wie könnts ich die Methoden aufrufen? Da ich das nicht weiss, wollte ich eine art Wrapper für die Methoden in eine weitere c++ klasse einarbeiten und diese dann aufrufen.
-
Wahrscheinlich würde man das in C# auch hinkriegen. Allerdings machen die ganzen structs dann einiges an Arbeit. Nicht sicher bin ich mir bei der Funktion Oak_Register_Callback, das übersteigt auch mein C# Wissen.
Aber auch in C++/CLI muss man da was tun
http://msdn.microsoft.com/de-de/library/367eeye0.aspx
oder eine gemischte DLL mit nativem C++ und einem in C++/CLI geschriebenen Teil zur Verwendung in .net bauen.
-
Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum MFC (Visual C++) in das Forum C++/CLI mit .NET verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.