unmanaged var as member of managed class c++ - class

I'm novice in .net c++ and trying to create class looking like:
public ref class Klient
{
public:
Klient(){}
// zmienne
static DWORD klienty[41][2];
static int i = 1;
static DWORD* pid;
static HANDLE* handle;
//funkcje
};
but MSV says that:
error C4368: cannot define 'klienty' as a member of managed 'Klient': mixed types are not supported
What's wrong with this code?

You can have .NET basic data types as members of your managed class (static int i), or pointers to anything unmanaged (DWORD* pid, HANDLE* handle), but you're not allowed to have an unmanaged object directly, and the array of integers counts as an unmanaged object for this purpose.
Since the only item giving you a problem here is the unmanaged array, you could switch it to a managed array.
public ref class Klient
{
public:
Klient(){}
// zmienne
static array<DWORD,2>^ klienty = gcnew array<DWORD,2>(41,2);
static int i = 1;
static DWORD* pid;
static HANDLE* handle;
//funkcje
};
Or, you can declare a unmanaged class, put whatever you need to in there, and have a pointer to it from the managed class. (If you do this in a non-static context, don't forget to delete the unmanaged memory from your finalizer.)
public class HolderOfUnmanagedStuff
{
public:
DWORD klienty[41][2];
int i;
DWORD* pid;
HANDLE* handle;
HolderOfUnmanagedStuff()
{
i = 1;
}
};
public ref class Klient
{
public:
Klient(){}
// zmienne
static HolderOfUnmanagedStuff* unmanagedStuff = new HolderOfUnmanagedStuff();
//funkcje
};

Related

c++/cli unmanaged library into managed code

I have the following code in c++/cli
`
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Konstruktorcode hier hinzufügen.
//
delegate int fooProc(UInt16);
}
...
public: void goTest(int x) { // declared in header
fooProc^ managed = gcnew fooProc(this, &Form1::foo);
IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(managed);
slave[x].module = static_cast<int(*)(unsigned short)>(stubPointer.ToPointer());
...
}
}
public: int foo(unsigned short test) {
Form1::label1->Text = "Hello success !";
...
return 1; // seems to not return to library function ( Run-Time Check Failure #0 - The value of ESP was not properly saved ...)
}
`
then in a static library with native code there is a function which calls the method 'foo' thru the pointer slave[x].module
as following:
int nativefoo(...) {
...
anyStruct[x].module(x); // struct defined in header
...
return 0;
}
The code crashes in method on return. Probably mismatch in calling conventions.
I have no idea how to solve this issue.
I only tried to alter and match the calling conventions. From __clrcall to __cdecl but no affect.

C++\CLI Windows Forms - creating external class

While making a simple windows forms application with VC++ I have a listview containing some files and their info. What I want to do is only show the filename in the list while storing the full filepath. I created an external class to do this:
class FileInfoContainer {
vector<string> filenames;
vector<int> uncompsize;
vector<int> compsize;
int getFileSize(string filepath);
public:
FileInfoContainer() {};
void AddItem(string filepath);
void AddItem(string filepath, int uncompsize, int compsize);
void AddItem(string filepath, int uncompsize);
string getItemFilename(int index);
int getItemCompsize(int index);
int getItemUncompsize(int index);
};
Now back to the automatic code generated by the VS template for this application, I tried to declare an instance of this class so that I can have the file information available anywhere within:
public ref class MainForm : public System::Windows::Forms::Form
{
public:
MainForm(void)
{
InitializeComponent();
}
protected:
~MainForm()
{
if (components)
{
delete components;
}
}
System::Windows::Forms::ListViewItem^ files; //my addition
FileInfoContainer compfiles; //my addition
private: System::Windows::Forms::OpenFileDialog^ openFileDialog1;
private: System::Windows::Forms::SaveFileDialog^ saveFileDialog1;
...........
}
This is generated code where I've only added those 2 lines, of which the first works normally while the second gives a member of managed class can't be non-managed class type error.
What can I do to go around this issue?

how to call member methods inside a wrapper class without repeating the method definition inside the wrapper class?

let's assume i have a wrapper class that embeds a single memeber:
class wrapper {
public:
Object obj;
// the rest ...
};
if the member variable obj has some methods, how can i call the member variable method without explicitly defining methods in the wrapper class like this?
class wrapper{
public:
void foo { obj.foo (); }
int bar (int x) {return obj.bar(x); }
};
i know this is doable in python, but how can i have the same functionality in c++?
ps- please note i don't want to inherit from the member class. this wouldn't't be a wrapper class by definition. i want to achieve this through composition instead.
There are a few ways to handle this. One would be to create a getter to return the wrapper object and another is to override the typecast operator:
class Object {
public:
void foo() {cout << "test" << endl;}
};
class wrapper {
protected:
Object obj;
public:
operator Object&() {return obj;}
Object& getObject() {return obj;}
};
void f(A& a) {
a.foo();
}
int main() {
wrapper w;
((Object)w).foo();
w.getObject().foo();
f(w);
return 0;
}
As you can see, the typecast operator requires you to cast the wrapper object, except when passing as a parameter to the function f().
Also, in your example you already have the obj member as public so it is exposed. You could just:
wrapper w;
w.obj.foo();
Here's a discussion on that: What good are public variables then?

Unmanaged method member being used as a delegate in managed class

I have a project where I am expanding existing native C++ compatible code functionality for a customer-facing library by integrating a driver from a managed DLL, which seems like the opposite direction for most marshaling questions. Since there can be multiple devices using this one driver, each device needs to be its own object, with its own callback methods. This integration will take the form of a native wrapper DLL that exposes the native class interface to the customer-facing library, which will pass an instance of a member method callback function pointer to the DLL. I need to pass a native method member instance (non-static) as a delegate to the managed wrapper class. The managed wrapper class uses GetDelegateForFunctionPointer, which works to marshal static native pointers to a delegate, but I can't find any information if it works with instances. GetDelegateForFunctionPointer also takes a System::IntPtr argument for the function pointer, but I'm also not sure if System::IntPtr works for instances, and when compiling in VC++2008 I'm being presented an error C3867 for attempting this.
Managed wrapper header:
//somemanagedclass.hpp
#pragma once
using namespace System;
using namespace ExternalManagedLibrary;
namespace SomeNameSpace
{
public ref class SomeManagedClass
{
public:
SomeManagedClass();
~SomeManagedClass();
delegate void CallbackHandler(const wchar_t*, int);
CallbackHandler^ CallbackEvent;
void RegisterCallback(IntPtr callbackEvent);
private:
ExternalManagedClass^ externalManagedClass;
void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
};
}
Managed wrapper source:
//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace System;
using namespace Runtime::InteropServices;
namespace SomeNameSpace
{
SomeManagedClass::SomeManagedClass()
{
externalManagedClass = gcnew ExternalManagedClass();
externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
SomeManagedClass::~SomeManagedClass()
{
externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
{
String^ some_string = String::Copy(e->Value);
cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
const wchar_t* p = pinned_string;
CallbackEvent(pinned_string, some_string->Length);
}
void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
{
CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
}
}
Native wrapper interface:
//somenativeinterface.hpp
#ifdef DLL_EXPORT
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT
typedef void (*NativeCallback)(const unsigned char*, unsigned long);
class IMPORT_EXPORT SomeNativeInterface
{
public:
//class factory
static SomeNativeInterface* Create(void);
static void Destroy(SomeNativeInterface* clInterface);
virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};
Native wrapper header:
//somenativeclass.hpp
#pragma once
#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace SomeNameSpace;
class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
public:
SomeNativeClass();
~SomeNativeClass();
void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?
private:
NativeCallback fnNativeCallback;
void OnNativeCallback(const wchar_t* cString, int iSize);
gcroot<SomeManagedClass^> wrapper; //warning C4251
};
Native wrapper source:
//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>
using namespace System;
using namespace Runtime::InteropServices;
SomeNativeInterface* SomeNativeInterface::Create()
{
return ((SomeNativeInterface*) new SomeNativeClass());
}
void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
delete instance;
}
SomeNativeClass::SomeNativeClass()
{
wrapper = gcnew SomeManagedClass();
}
SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
size_t iCharsConverted;
if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
{
if (iCharsConverted > 0xFFFFFFFF)
iCharsConverted = 0xFFFFFFFF; //truncate
fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
}
}
SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
fnNativeCallback = fnNativeCallbackInit;
wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}

C++/CLI class wrapper for c library - callbacks

I am wrapping a C library using C++/CLI. The C library was designed to be used from an unmanaged C++ class. This means that the library functions accept a C++ object pointer and then provide that pointer back in callbacks. This enables the callback code to redirect requests to an appropriate event function in the calling C++ object.
The actual functions are quite involved, so I have simplified the problem space to just a few basic items:
// C library function signature
void CLibFunc(CLIBCALLBACK *callback, void *caller);
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C callback implementation
int CallBackImpl(int param1, void* caller)
{
// Need to call the ManagedCaller's EventFunction from here
// ???
}
// C++/CLI caller class
public ref class ManagedCaller
{
public:
void CallerFunction(void)
{
// Call the C library function
// Need to pass some kind of this class pointer that refers to this object
CLibFunc(CallBackImpl, ????);
}
void EventFunction(param1)
{
}
}
Now the C library functions need to be called from a managed C++ class. Under C++/CLI, the garbage collector moves objects around in memory, so passing a simple fixed pointer to the class does not work anymore. I can solve the problem by pinning the object, but that is not recommended because it leads to memory fragmentation. It seems that another option would be to use auto_gcroot pointers, but I am fairly new to managed C++ an I am not sure how to make this work.
Does anyone know how to make this work? What kind of pointer should be passed to the C function? How should the callback implementation redirect to the calling object's event function?
This just happens to be similar to something I'm in the middle of working on right now.
Here is an blog post on providing native callbacks using C++ classes: http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx
I'm not familiar with calling C++ member functions from C, but I have done an interface (abstract base) class to another C++ class for callbacks (similar to the article). Here is a basic example of what I am providing a bridge for:
// Interface (abstract base) class providing the callback
class IProvider {
public:
virtual ~IProvider() {}
virtual void Callback() = 0;
};
// User class of the callback
class CUser {
IProvider * m_pProvider;
public:
CUser(IProvider * pProvider) {
m_pProvider = pProvider;
}
void DoSomething() {
m_pProvider->Callback();
}
};
// Implementation of the interface class
class CHelloWorldProvider : public IProvider {
void Callback() {
printf("Hello World!");
}
};
// Usage of the callback provider in a pure native setting
void PureNativeUsage() {
CHelloWorldProvider oProvider;
CUser oUser(&oProvider);
oUser.DoSomething();
}
Now in order to make this available for managed implementations of the provider, we have to create a series of classes that provide the bridge.
// Where gcroot is defined
#include <vcclr.h>
// Managed provider interface class
public interface class IManagedProvider {
void Callback();
};
// Native bridge class that can be passed to the user
class CProviderBridge : public IProvider {
// Give the managed class full access
friend ref class ManagedProviderBase;
// Store a reference to the managed object for callback redirects
gcroot<IManagedProvider ^> m_rManaged;
public:
void Callback(){
m_rManaged->Callback();
}
};
// Managed provider base class, this provides a managed base class for extending
public ref class ManagedProviderBase abstract : public IManagedProvider {
// Pointer to the native bridge object
CProviderBridge * m_pNative;
protected:
ManagedProviderBase() {
// Create the native bridge object and set the managed reference
m_pNative = new CProviderBridge();
m_pNative->m_rManaged = this;
}
public:
~ManagedProviderBase() {
delete m_pNative;
}
// Returns a pointer to the native provider object
IProvider * GetProvider() {
return m_pNative;
}
// Makes the deriving class implement the function
virtual void Callback() = 0;
};
// Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net)
public ref class ManagedHelloWorldProvider : public ManagedProviderBase {
public:
virtual void Callback() override {
Console::Write("Hello World");
}
};
// Usage of the managed provider from the native user
void MixedUsage() {
ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider;
CUser oUser(rManagedProvider->GetProvider());
oUser.DoSomething();
}
Edit: Added code to show w/o the managed interface class example I use.
Here is a modified version of my example that can be used given your CLibFunc above. This is assuming how the C function performs the callback is accurate.
Also this might be able to be slimmed down a bit depending on how involved your callback classes are and how much freedom for extension you need.
// Where gcroot is defined
#include <vcclr.h>
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C library function
void CLibFunc(CLIBCALLBACK *callback, void *caller) {
// Do some work
(*callback)(1234, caller);
// Do more work
}
// Managed caller interface class
public interface class IManagedCaller {
void EventFunction(int param1);
};
// C++ native bridge struct
struct CCallerBridge {
// Give the managed class full access
friend ref class ManagedCaller;
// Store a reference to the managed object for callback redirects
gcroot<IManagedCaller ^> m_rManaged;
public:
// Cast the caller to the native bridge and call managed event function
// Note: This must be __stdcall to prevent function call stack corruption
static int __stdcall CallBackImpl(int param1, void * caller) {
CCallerBridge * pCaller = (CCallerBridge *) caller;
pCaller->m_rManaged->EventFunction(param1);
return 0;
}
};
// C++/CLI caller class
public ref class ManagedCaller : public IManagedCaller {
// Pointer to the native bridge object
CCallerBridge * m_pNative;
public:
ManagedCaller() {
// Create the native bridge object and set the managed reference
m_pNative = new CCallerBridge();
m_pNative->m_rManaged = this;
}
~ManagedCaller() {
delete m_pNative;
}
// Calls the C library function
void CallerFunction() {
CLibFunc(CCallerBridge::CallBackImpl, m_pNative);
}
// Managed callback function
virtual void EventFunction(int param1) {
Console::WriteLine(param1);
}
};
// Usage
int main(array<System::String ^> ^args) {
ManagedCaller ^ oCaller = gcnew ManagedCaller();
oCaller->CallerFunction();
return 0;
}