I have a Java project in which I use some C++ code using JNI.
I encountered a weird problem.
I have a class that looks more or less like so:
class MyClass
{
private:
MyType* _p;
public:
MyClass();
virtual ~MyClass();
void myFunc();
};
And:
MyClass::MyClass() : _p(NULL) {
// _p's value here is indeed NULL (0)
}
MyClass::~MyClass() {
}
void MyClass::myFunc() {
if (_p != NULL) {
delete _p;
}
_p = new MyType();
}
No other function but myFunc touches _p, and for some reason, even after initializing it to NULL, when calling myFunc for the first time, _p has some garbage value in it and the function attempts to delete it.
The ctor of MyClass is called using JNI, and myFunc is too called using JNI, on a separate occasion.
Any help would be greatly appreciated.
Related
I have a very simple and yet complicated (atleast for me) question on how to call a method/function outside a class but on a same namespace in c++/cli.
I know that you need to create an instance of an object before you can call a method which is inside a class, something like:
namespace Cars {
public ref class MyClass
{
void Honda(int i)
{
//some code
}
}
void Register()
{
MyClass c;
c.Honda(1);
//some code
}
}
But how do I do the opposite? Like how do I call Register() inside the MyClass::Honda function if they are on the same namespace but not on the same class?
I tried Cars::Register() but it gives an error saying that:
Register() is not a member of "Cars".
Edit: I added the actual code that I tried to access the Register() method.
namespace Cars {
public ref class MyClass
{
void Honda(int i)
{
Cars::Register();
}
}
void Register()
{
//some code
}
}
The line Cars::Register(); do not give any error when I save but when I try to rebuild my application it gives the error below:
Error C2039 'Register': is not a member of 'Cars'
Error C3861 'Register': identifier not found
Just to note that when I put Register() inside the MyClass, everything works well (for some reason I just need to put it outside the class)
Thanks!
There are 2 issues in your code:
Missing ; at the end of the definition for ref class MyClass.
Register() should be defined (or at least declared) before calling it.
Fixed version:
namespace Cars
{
// Defintion:
void Register()
{
//some code
}
public ref class MyClass
{
void Honda(int i)
{
Cars::Register();
}
};
}
Or alternatively:
namespace Cars
{
// Declaration:
void Register();
public ref class MyClass
{
void Honda(int i)
{
Cars::Register();
}
};
// Definition:
void Register()
{
//some code
}
}
Note: since you call Register within the same namespace, you can actually drop the Cars:: qualifier, i.e. simply call: Register();. You also keep it of course, if you think it improves readability.
I'm attempting to run a function concurrently using QtConcurrent but I'm running into issues with one of the arguments.
As a precursor, lets say I have the following classes and "interfaces":
class DataMessage : public QObject {
Q_OBJECT
// ... fields and methods
};
class ITimeStampInfo {
public:
virtual QDateTime timestamp() const = 0;
};
Q_DECLARE_INTERFACE(ITimeStampInfo, "My.TimeStampInfo/1.0")
class IDataLengthInfo {
public:
virtual int dataLength() const = 0;
};
Q_DECLARE_INTERFACE(IDataLengthInfo, "My.IDataLengthInfo/1.0")
class DataMessage1 : public DataMessage, public ITimeStampInfo {
Q_OBJECT
Q_INTERFACES(ITimeStampInfo)
// other fields, etc
QDateTime timestamp() const;
};
class DataMessage2 : public DataMessage, public IDataLengthInfo {
Q_OBJECT
Q_INTERFACES(IDataLengthInfo)
// other fields
int dataLength() const;
};
And a class function called processDataMessages:
void MyClass::processDataMessages(DataMessage *msg) {
// Previous to this function being called, concrete `DataMessage`
// instances are created and passed by pointer into this function
// Determine the data in the message
IDataLengthInfo *dl = qobject_cast<IDataLengthInfo*>(msg);
if (dl) {
qDebug() << "Got a message with IDataLengthInfo";
}
ITimeStampInfo *ts = qobject_cast<ITimeStampInfo*>(msg);
if (ts) {
qDebug() << "Got a message with ITimeStampInfo";
}
// etc
}
This processDataMessages is called in a slot. During normal operation, this function works perfectly and the qDebug() statements execute as expected as the pointer is correct - for example, inspecting the pointer type in the debugger results in a DataMessage1 type, for instance
I now want to run this function asynchronously as potentially, there may be a bit of work to do. If I try to execute this function using QtConcurrent::run from within the slot as follows:
void MyClass::dataReceived(DataMessage *msg) {
// this->processDataMessages(msg);
QtConcurrent::run(this, &MyClass::processDataMessages, msg);
}
Now when I break on the first qobject_cast line in the processDataMessages function, I can see that the msg pointer is of type DataMessage and not any of the DataMessage1 or DataMessage2 types.
Something is being lost during the operation of QtConcurrent::run and its probably something dumb I've missed.
Ok, so as it turns out, the following code works:
QFuture<void> f = QtConcurrent::run(this, &MyClass::processDataMessages, msg);
// Wait for the function to finish
f.waitForFinished();
Doesn't really seem any different to the original but something in the return value may be maintaining state??
I'm working on a student project. It's a network card game. The solution contains 3 projects. Client's GUI using Windows Forms so it has managed classes. Static client's library in native C++. GUI's project has reference to it thus uses 'Mixed Rules'. Server is in native C++ as well. I use RPC middleware for communication. It works only with native C++. That is why I need the static library to hide there all the details of communication on client's side.
Since the server can at any moment change its state and that should be shown in client's GUI, I use callback approach to change Windows Forms' components. And here I found a problem because I need to change private members of managed class with the help of a native object.
There are probably different ways to do that. My idea is sending a pointer to instance of managed class into instance of native class and saving it there. So later I can call from that native object public member functions of that managed class to change components.
This is from my 'Mixed Rules' GUI project:
//Native class for changing window 'Lobby'
class LobbyI : public ClientLib::Lobby {
public:
LobbyI();
~LobbyI();
//Should change window due to current Server's state
void reDraw(const CommonLogic::ServerState&);
};
// Managed class implements GUI for window 'Lobby'
// generated by Visual Studio designer
public ref class LobbyGUI : public System::Windows::Forms::Form {
//My members
ClientLib::Mediator* mediatorPtr; // Is it correct?
LobbyI* lobbyPtr; // ?
public:
LobbyGUI(void) {
InitializeComponent();
mediatorPtr = new ClientLib::Mediator(); // Is it correct?
lobbyPtr = new LobbyI(); // ?
mediatorPtr->setCallback(lobbyPtr);
}
protected:
~LobbyGUI() {
if (components) { delete components; }
delete lobbyPtr; // Is it correct?
lobbyPtr = nullptr; // ?
delete mediatorPtr; // ?
mediatorPtr = nullptr; // ?
}
private: System::Windows::Forms::Button^ buttonLogIn;
//...
This is from native static library ClientLib:
class Lobby {
public:
virtual ~Lobby();
virtual void reDraw(const CommonLogic::ServerState&) = 0;
};
class Mediator {
CommonLogic::ServerState serverState;
Lobby* lobbyPtr;
public:
Mediator();
~Mediator();
void setCallback(Lobby* ptr) { lobbyPtr = ptr; }
void reDrawLobby() { lobbyPtr->reDraw(serverState); }
};
This code builds ok. The only thing I need now is that the member function reDraw() of native derived class LobbyI is able to change the window implemented by managed class LobbyGUI. Thus getting and keeping and using pointer to it. And then I think it all will work. How to do that?
Maybe it's not the nicest implementation in general. I would be happy to read other suggestion.
I'm also doubtful about the way I used pointers to native classes inside managed class. Is it correct? It didn't work correct until I inserted ptr=nullptr; after delete ptr; in destructor.
UPDATE: Now I see redundancy in my code. Abstract class Lobby is useless. I need only to implement reDraw() function in managed class which will have obviously access to components of the window. And then pass safe pointer to native class function which expects pointer to a function as a parameter.
Finally I've solved it!! Using this article. In the following code a native object stores provided pointer to a function of managed object. So this callback function can be invoked at any time. A delegate is used as a form of type-safe function pointer. Instance of GCHandle is used to prevent the delegate from being relocated by garbage collector.
Here is simple CLR Console Application which increments and prints some integer using callback function invoked from native object. Thus we can "change private members of managed object using a native one".
using namespace System;
using namespace System::Runtime::InteropServices;
typedef void(__stdcall *ANSWERCB)(); // define type of callback function
#pragma unmanaged
class NativeClass {
ANSWERCB cbFuncPtr = 0; // pointer to callback function
public:
void setCallback(ANSWERCB fptr) {
cbFuncPtr = fptr;
incAndPrint();
}
void incAndPrint() { cbFuncPtr(); } // invokes callback which increments and prints
};
#pragma managed
ref class ManagedClass {
public: delegate void Del();
private:
Int32 i;
NativeClass* nativePtr;
Del^ delHandle;
GCHandle gch;
public:
ManagedClass(Int32 ii) : i(ii) {
nativePtr = new NativeClass;
delHandle = gcnew Del(this, &ManagedClass::changeAndPrintInt);
gch = GCHandle::Alloc(delHandle);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(delHandle);
ANSWERCB callbackPtr = static_cast<ANSWERCB>(ip.ToPointer());
nativePtr->setCallback(callbackPtr);
}
~ManagedClass() {
delete nativePtr;
nativePtr = __nullptr;
gch.Free();
}
private:
void changeAndPrintInt() // callback function
{
Console::WriteLine(++i);
}
};
int main(array<System::String ^> ^args)
{
ManagedClass mc(1);
return 0;
}
I have to deal with code that can be reduced as follows:
void main ()
{
class MyBase
{
public:
virtual void MyFunc () = 0;
};
class MyClass : public MyBase
{
public:
virtual void MyFunc () {}
};
MyClass x;
}
When compiling under Visual-C++ 2010 with `cl /nologo /Wall text.cxx', I get the following warning:
test.cxx(7) : warning C4101: 'main::MyBase::MyFunc' : unreferenced local variable
I want to keep MyBase in place if possible (because it is deep down inside the code hierarchy).
Is there a way to 'fix' the code in place (other than using #pragma to ignore the warning)? Or is it bad practice to have a local abstract class?
Thanks in advance!
I have the following scenario. The managed code will initialize lots of object of a class which is a wrapper around an unmanaged struct. There are two approaches that I can do for this. One is to have a managed class wrapper that just has a pointer to the unmanaged object. The other is to have a full fledged managed class and create the unmanaged object when required to call into unmanaged methods. I have provided both the methods below. I was told that if I use the approach 1(having a pointer to unmanged object), the GC will have lots of issue knowing about the unmanaged portion and it is better to do approach 2. Does someone tell me which is better or if there is some other approach that is even better. My concern with Approach 2 is that there are copying to and fro everytime a unmanaged method is called. I am not sure if the GC issue outweighs it.
EDIT- the first approach has a ref class and the second has a value class. The reason the second is value is so that it can be added to lists more efficiently
In unmanaged:
struct A_UNMANAGED
{
int a;
int b[20];
};
void GetData(A_UNMANAGED& a); // populates A
In managed (First Approach)
public ref class A_MANAGED
{
A_UNMANGED* ap;
public:
property System::UInt32 a
{
System::UInt32 get() { return ap->a; }
void set(System::UInt32 value) { ap->a = value; }
}
property array<System::UInt32>^ b
{
array<System::UInt32>^ get() { return ap->b; }
void set(array<System::UInt32>^ value) { b = value; } // assume this copy works
}
internal:
void GetData()
{
GetData(ap);
}
};
In managed (Second Approach) (EDIT: updated to ref. Assume all the garbage collection and pointer creation is written correctly)
public value class A_MANAGED
{
System::UInt32 a;
array<System::UInt32>^ b;
public:
property System::UInt32 a
{
System::UInt32 get() { return a; }
void set(System::UInt32 value) { a = value; }
}
property array<System::UInt32>^ b
{
array<System::UInt32>^ get() { return b; }
void set(array<System::UInt32>^ value) { b = value; }
}
internal:
void GetUnmanaged(A_UNMANAGED& obj1)
{
obj1.a = a;
pin_ptr<System::UInt32> bp = &b[0];
memcpy(obj1.b, bp, 20);
}
void GetData()
{
A_UNMANAGED obj2;
GetUnmanaged(obj2);
GetData(obj2);
// copy from obj2 to member variables
}
};
No, the 1st snippet it the canonical way. The garbage collector only moves the pointer, it doesn't move the pointed-to object. That one should have been allocated with malloc() or the new operator, it cannot be moved.
There are otherwise several serious problems in your code. You don't seem to allocate the memory for A_UNMANAGED unless GetData() takes its argument by reference. GetData() is never called. This must normally be a ref class (not ref value) so you can provide a destructor and a finalizer to release the memory. The b property setter will bomb your program with a StackOverflowException. Be sure to study the language before tackling this project.
Check this answer for sample code.
As Hans said, the first way is the usual approach (though personally, I think P/Invoke would be more succinct in this particular case...). However, your A_MANAGED::b implementation will not work, which would be obvious if one were to try simply compiling it. Try this instead:
public ref class A_MANAGED
{
A_UNMANAGED* ap;
public:
A_MANAGED() : ap(new A_UNMANAGED() ) { }
~A_MANAGED() { this->!A_MANAGED(); }
!A_MANAGED() { delete ap; ap = nullptr; }
property int a
{
int get() { return ap->a; }
void set(int value) { ap->a = value; }
}
property array<int>^ b
{
array<int>^ get()
{
using System::Runtime::InteropServices::Marshal;
array<int>^ arr = gcnew array<int>(20);
Marshal::Copy(System::IntPtr(ap->b), arr, 0, 20);
return arr;
}
void set(array<int>^ value)
{
using System::Runtime::InteropServices::Marshal;
Marshal::Copy(value, 0, System::IntPtr(ap->b), 20);
}
}
internal:
void GetData()
{
::GetData(*ap);
}
};
And then there's the usual caveat about returning arrays from properties: it's a bad idea. Unless you really want to maintain parity with the unmanaged class' public interface, b should really be a pair of set/get functions rather than a property.