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.


Anmelden zum Antworten