Why is happened property write error? - properties

c++ : Run time error is happened with error message like this:
RevStrings1->Height of reading included in error: The property is write-protected.
RevStrings1->Height の読み込中のエラー : プロパティは書き込み禁止です.
I'm using c++ builder 3.
This source code can be successfully compiled
setting library, include path and etc.
But run time error is happened.
I guess that this problem is about property read & write.
How can I simplly fix the problem ?
A variable RevStrings1 is created by a class TRevStrings.
//---------------------------------------------------------------------------
#ifndef RevStringsH
#define RevStringsH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
class PACKAGE TRevStrings : public TStringGrid
{
private:
// void __fastcall SetWidth(int W);
// int __fastcall GetWidth(void);
// int FColCount ;
int FRowCount;
int FFixedCols ;
int FFixedRows ;
int FDefaultColWidth ;
int FDefaultRowHeight ;
int FHeight;
// int FWidth;
int FScrollBars;
int FMaxLength;
bool ColColors[24];
protected:
public:
__fastcall TRevStrings(TComponent* Owner);
void __fastcall DrawCellText(TRect ARect,int ALeft,String S);
virtual void __fastcall DrawCell(int ACol, int ARow,const Windows::TRect &ARect, TGridDrawState AState);
void __fastcall SetColor_Col(int Col,int Row);
void __fastcall SetColorFlag(int Col,bool flag);
bool __fastcall GetColorFlag(int Col);
void __fastcall SetEditText(int ACol, int ARow,const System::AnsiString Value);
void __fastcall Clear(bool ALLorONE,int Position);
void __fastcall DblClick(void);
__published:
// __property int ColCount = {read = FColCount};//FColCount};
__property int RowCount = {read=FRowCount};
__property int FixedCols = {read=FFixedCols};
__property int FixedRows = {read=FFixedRows};
__property int DefaultColWidth = {read=FDefaultColWidth};
__property int DefaultRowHeight = {read=FDefaultRowHeight};
__property int Height = {read=FHeight};
// __property int Width = {read=GetWidth,write=SetWidth};
__property int ScrollBars = {read=FScrollBars};
__property int MaxLength = {read=FMaxLength,write=FMaxLength};
/*
*/
};
//---------------------------------------------------------------------------
#endif

never heard of TRevStrings before
so it is either BCB 3 discontinued stuff (my BDS2006 does not have it at disposal) or you have some 3th party custom package installed but the header file suggest it is based on TStringGrid so if below text does not work for it then you can switch to TStringGrid instead.
in TStringGrid
size properties are accessible normaly:
StringGrid1->Height=256;
StringGrid1->Width=128;
if you want to have size-able col/rows then do not forget to open Options property and set goRowSizing,goColSizing to true and starting sizes are DefaultColWidth,DefaultRowHeight. Here example of usage
// resize the grid
StringGrid1->Height=128;
StringGrid1->Width=256;
// access to Cell AnsiStings
StringGrid1->Cells[0][0]="(0,0)";
StringGrid1->Cells[1][1]="(1,1)";
StringGrid1->Cells[1][2]="(1,2)";
StringGrid1->Cells[2][1]="(2,1)";
// resizing row/col
StringGrid1->RowHeights[0]=15;
StringGrid1->RowHeights[1]=20;
StringGrid1->ColWidths[0]=20;
StringGrid1->ColWidths[1]=15;
As your class is derived from this so this should work also for it if not the there are more possibilities:
you have unrelated bug somewhere
overwriting what you should not damaging the C++ engine your App is running on or have memory leak somewhere or your memory manager is invalidated see
bds 2006 C hidden memory manager conflicts
but that is probably not the case or you are calling VCL/Winapi visual stuff from threads.
To check for all this:
create empty application, add your TRevString and try to set its height on runtime. If no error occurs you have a bug somewhere if error occurs then:
this component is not able to resize on runtime this way
try to use functions like SetSize,SetBounds instead or place the component on some panel align to Client and resize panel
if even this does not help switch to standard TStringGrid
you can also try to cast you RevString to StringGrid first
((TStringGrid*)(RevString1))->Height=25;
Borland compilers sometimes get weird
few times (around 10) over the years I use BCB/BDS the compiler sometimes compile wrongly. The app is running but some code gets distorted or discarted so what helps?
close IDE or even restart Windows
delete all map,obj,tds temp files prior to compiling rebuilding
sometimes is needed that you add empty line of code or swap 2 lines of code
Identifiers/Names collisions
if you name your stuff in similar way to VCL functions then you ask for problems usual error is to name function Draw() ... (use draw() instead and you are fine)
for big projects
if you add your source code as new unit to project instead of just include it (it is present in Object Manager) then in big projects you will got big problems. It looks like units are compiled differently then normal included files in units are expected Formulars and other VCL stuff components so if you got your own non visual classes as units they sometimes stop working as expected creating weird behavior (even your error could be caused by it).
I observe this on BCB5 and BDS2006. In BCB3,BCB4 I did not make big enough projects to spot this and BCB6 is so buggy so its unusable with big projects anyway. By big projects I mean > 1 MB of pure C++ code

The error is self-explanatory - the Height property of the RevStrings1 object is not allowing its value to be assigned. This is evident by looking at the declaration of the Height property in the TRevStrings class:
__property int Height = {read=FHeight};
TRevStrings is going out of its way to make the Height property read-only, overriding the native read-write Height property that is inherited from TControl:
__property int Height = {read=FHeight, write=SetHeight, nodefault};
This is odd for TRevString to do, as it is a visual component that needs to be sizable. Unless it requires a specific height that the user cannot change (in which case declaring the Height property as read-only is not the correct way to handle that - the component should override the virtual SetBounds() method instead and just ignore any new Height value being assigned).
That being said, the reason you see the error at run-time is because the IDE is storing the design-time Height value of the RevStrings1 object in the parent Form's DFM resource at compile-time. That is why you are not finding any RevStrings1->Height in your code - it is coming from the Form Designer instead. The TRevStrings class is not overriding DFM behavior for the Height property, so when the VCL's DFM streaming system parses the Form's DFM resource at run-time, it sees the stored Height value and detects that the object's Height property is actually read-only, and so throws an exception to cancel DFM streaming (and thus the Form's construction).
This is a bug in the TRevStrings implementation. At the very least, if the author had wanted to prevent the Height from being streamed (thus preventing the run-time error), the Height property should have been declared like this instead:
__property Height = {read=FHeight, stored=false};
On a side note, most of the TRevStrings data members (FColCount, FRowCount, FFixedCols, FFixedRows, etc) should never have been declared at all, but instead should have been inherited from the base TStringGrid class.
Whoever wrote this component clearly did not know what they were doing.

Related

(C++/CLI) How to get callbacks from Native Code to Managed Code in C++ CLI?

RANT-BEGIN
Before jumping right into already answered band wagon, please read this paper about SE outdated answers https://ieeexplore.ieee.org/document/8669958
Things changes after a time, and I am afraid Computer science is one of the most if not the most field out there where APIs and Interfaces change radically very very fast. Needless to say that a solution that might worked last month might not after latest feature added to a platform/framework. I humbly request you to not mark this question as answered with decade old post when many mainstream things did not even existed. If you dont know latest solution dont bother about it and leave question for someone else who might.
For a community representative of Computer Science where innovations is everyday thing, it is very toxic, new comer unfriendly and conservative.
END-RANT
This question has already been answered by me and will be accepted tomorrow (SE policy). Thank you for your interest.
Many times you have function pointers in unmanaged context which are called by some kind of events, We will see how it can be achieved with Top-Level Functions and also with member functions of a managed class.
Again, Please dont mark it as answered by linking to a decade old posts.
PS:
So many edits due to unstable internet in third world country, yeah bite me!
unmanaged.cpp
#pragma unmanaged
// Declare an unmanaged function type that takes one int arguments and callbacks
// our function after incrementing it by 1
// Note the use of __stdcall for compatibility with managed code
// if your unmanaged callback uses any other calling convention you can
// UnmanagedFunctionPointerAttribute (check msdn for more info) on your delegate
typedef int(__stdcall* ANSWERCB)(int);//Signature of native callback
int TakesCallback(ANSWERCB fp, int a) {
if (fp) {
return fp(a+1);//Native Callback
}
// This code will be executed when passed without fp
return 0;
}
#pragma managed
managed.cpp
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Callbacks {
// Following delegate is for unmanaged code and must match its signature
public delegate void MyNativeDelegate(int i);
// This delegate is for managed/derived code and ideally should have only managed parameters
public delegate void MyManagedDelegate(int i);
public ref class TestCallback {// Our demo Managed class
private:
GCHandle gch;// kept reference so that it can be freed once we are done with it
void NativeCallbackListener(int i);//unmanaged code will call this function
public:
void TriggerCallback(int i); // Its here for demo purposes, usually unmanaged code will call automatically
event MyManagedDelegate^ SomethingHappened;//plain old event
~TestCallback();//free gch in destructor as its managed.
};
};
void Callbacks::TestCallback::NativeCallbackListener(int i) {
// Callback from Native code,
// If you need to transform your arguments do it here, like transforming void* to somekind of native structure.
// and then pass SomethingHappened::raise with Managed Class/Struct
return SomethingHappened::raise(i); // similar to SomethingHappened.Invoke() in c#
}
void Callbacks::TestCallback::TriggerCallback(int i)
{
MyNativeDelegate^ fp = gcnew MyNativeDelegate(this, &TestCallback::NativeCallbackListener);
// use this if your nativecallback function is not a member function MyNativeDelegate^ fp = gcnew MyNativeDelegate(&NativeCallbackListener);
gch = GCHandle::Alloc(fp);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());// (ANSWERCB)ip.ToPointer(); works aswell
// Simulating native call, it should callback to our function ptr NativeCallbackListener with 2+1;
// Ideally Native code keeps function pointer and calls back without pointer being provided every time.
// Most likely with a dedicated function for that.
TakesCallback(cb, i);
}
void Callbacks::TestCallback::~TestCallBack() {
gch.Free();//Free GCHandle so GC can collect
}
implementation.cpp
using namespace System;
void OnSomethingHappened(int i);
int main(array<System::String^>^ args)
{
auto cb = gcnew Callbacks::TestCallback();
cb->SomethingHappened += gcnew Callbacks::MyManagedDelegate(&OnSomethingHappened);
cb->TriggerCallback(1);
return 0;
}
void OnSomethingHappened(int i)
{
Console::WriteLine("Got call back with " + i);
}

C++-CLI how do I convert String^ (from a textbox) to something that a function which takes void* type variables, will accept?

I have the following function from a dll:
aisgdll_setinfo(int dev, set_field_code field, void *data);
I know how to deal with the first two parameters. I have a textbox the user enters data into and the textbox returns a variable of type String^. I somehow need to get the data from that textbox and do something, so that I can write it to this function to the void *data parameter.
You can use this form.
I used the Thread :: Sleep to prevent abuse in processing. While your thread does not change the status of the screen will be updated.
void solve()
{
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Threading;
Thread^ bot_thread = gcnew Thread(gcnew ThreadStart(bot_run));
bot_thread->Start();
PictureBox^ PB_LoadGIF = gcnew PictureBox();
PB_LoadGIF->Visible = true;
while (bot_thread->ThreadState == ThreadState::Running)
{
Thread::Sleep(1000);
PB_LoadGIF->Parent->Refresh();
}
}
After further research online, I have found some solutions to the problems I was having. The functions I was plugging the retrieved values into needed pointers. I think these solutions can be adapted by others for their own purposes. For converting the Visual Studio Text box String^ to char*:
char* iData = (char*)Marshal::StringToHGlobalAnsi(activeBox->Text).ToPointer();
When I needed to get a floating point number from a Text box, I used the following:
int anInteger = (int)((Convert::ToDouble(activeBox->Text))*10);
int *iData = &anInteger;

Using Marshal::GetFunctionPointerForDelegate and calling a callback from unmanaged code causes a buffer overrun when quitting application

I am using Visual Studio 2008 with .NET Framework 3.5 and making a C++/CLI/.NET Forms application; an editor for a game. All the game code other than the editor is in pure C++. I'm getting to a point where I need callbacks in the Forms code to be called from unmanaged code.
I'm using GetFunctionPointerForDelegate.
First I have these in my Form class:
public: delegate void ADelegate(Int32, float, float, float, Int32);
public: static ADelegate^ delegateInstance;
Then I set up the callback in the Form constructor:
// Set up World Objects callback
typedef void (__stdcall *WorldLocationUpdateCallback)(Int32, float, float, float, Int32);
WorldLocationUpdateCallback _callback;
// Create an instance of a delegate, using GetFunctionPointerForDelegate
delegateInstance = gcnew ADelegate( this, &MainForm::InitWorldObjectPane );
// Convert the delegate to a pointer
IntPtr anIntPtr = Marshal::GetFunctionPointerForDelegate( delegateInstance );
// Cast the pointer into a function pointer
_callback = static_cast<WorldLocationUpdateCallback>(anIntPtr.ToPointer());
CEditorUI::UI()->setWorldLocationUpdateCallback( (void*)_callback );
So I store the pointer and in the unmanaged code, call the callback early on in the initialization of my app, from a different thread:
// Set up World Object pane in editor to use this map/maptile/etc
{
typedef void (*WorldLocCallback)(int, float, float, float, int);
void* _callback = CEditorUI::UI()->getWorldLocationUpdateCallback();
int _mapId = charGfxObj->getMapId();
float _posX = charGfxObj->getPos().x;
float _posY = charGfxObj->getPos().y;
float _posZ = charGfxObj->getPos().z;
int _tileRadius = TILE_RADIUS;
((WorldLocCallback)(_callback))( _mapId, _posX, _posY, _posZ, _tileRadius );
}
Everything works perfectly, functionally in my app, all the way until when I close the application. It always dies with a Buffer overrun error in the calling thread, the call stack being rather unhelpful:
editor.exe!__crt_debugger_hook() Unknown
>editor.exe!__report_gsfailure() Line 298 + 0x7 bytes C
editor.exe!__CorExeMain#0() + 0xe3 bytes C++
The kicker here is that it crashes even if the callback does literally nothing at all. All I have to do to cause the crash is to enable that last line of code that calls the callback. With that line disabled, no problems. Keep in mind the crash happens only when quitting, and not when actually using the callback.
Any recommendations to try?
After an entire day messing with this and searching for other related things, I somewhat solved this, in case anyone else has this issue.
Moving the delegate declaration outside the class and decorating it with:
[UnmanagedFunctionPointerAttribute(CallingConvention::Cdecl)]
...solved it for me. Apparently the stack clearing effect of cdecl solves the overrun.

Using XNA Math in a DLL Class

I'm having a problem in using XNA Math in a DLL I'm creating. I have a class that is in a DLL and is going to be exported. It has a member variable of type XMVECTOR. In the class constructor, I try to initialize the XMVECTOR. I get a Access Violation in reading from reading location 0x0000000000
The code runs something like this:
class DLLClass
{
public:
DLLClass(void);
~DLLClass(void);
protected:
XMVECTOR vect;
XMMATRIX matr;
}
DLLClass::DLLClass(void)
{
vect = XMLoadFloat3(&XMFLOAT3(0.0f, 0.0f, 0.0f)); //this is the line causing the access violation
}
Note that this class is in a DLL that is going to be exported. I do not know if this will make a difference by just some further info.
Also while I'm at it, I have another question:
I also get the warning: struct '_XMMATRIX' needs to have dll-interface to be used by clients of class 'DLLClass'
Is this fatal? If not, what does it mean and how can I get rid of it? Note this DLLClass is going to be exported and the "clients" of the DLLClass is probably going to use the variable 'matr'.
Any help would be appreciated.
EDIT: just some further info: I've debugged the code line by line and it seems that the error occurs when the return value of XMLoadFloat3 is assigned to the vect.
This code is only legal if you are building with x64 native -or- if you use __aligned_malloc to ensure the memory for all instances of DLLClass are 16-byte aligned. x86 (32-bit) malloc and new only provide 8-byte alignment by default. You can 'get lucky' but it's not stable.
class DLLClass
{
public:
DLLClass(void);
~DLLClass(void);
protected:
XMVECTOR vect;
XMMATRIX matr;
}
See DirectXMath Programming Guide, Getting Started
You have three choices:
Ensure DLLClass is always 16-byte aligned
Use XMFLOAT4 and XMFLOAT4X4 instead and do explicit load/stores
Use the SimpleMath wrapper types in DirectX Tool Kit instead which handle the loads/stores for you.
You shouldn't take the address of an anonymous variable:
vect = XMLoadFloat3(&XMFLOAT3(0.0f, 0.0f, 0.0f));
You need
XMFLOAT3 foo(0.0f, 0.0f, 0.0f);
vect = XMLoadFloat3(&foo);

C Callback in Objective-C (IOKIT)

I am trying to write some code that interacts with an USB device in Objective C, and I got stuck on setting the callback function for incoming reports. In my case it's an IOKIT function but I think the problem is more general as I (apparently) don't know how to correctly set a C callback function in Objective-C. I've got a Class "USBController" that handles the io functions
USBController.m:
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>
#import "USBController.h"
static void Handle_IOHIDDeviceIOHIDReportCallback(
void * inContext, // context from IOHIDDeviceRegisterInputReportCallback
IOReturn inResult, // completion result for the input report operation
void * inSender, // IOHIDDeviceRef of the device this report is from
IOHIDReportType inType, // the report type
uint32_t inReportID, // the report ID
uint8_t * inReport, // pointer to the report data
CFIndex InReportLength) // the actual size of the input report
{
printf("hello"); //just to see if the function is called
}
#implementation USBController
- (void)ConnectToDevice {
...
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
...
}
...
#end
All the functions are also declared in the header file.
I think I did pretty much the same as what I've found here, but it doesn't work. The project compiles nicely and everything works up till the moment there is input and the callback function is to be called. Then I get an "EXC_BAD_ACCESS" error. The first three arguments of the function are correct. I'm not so sure about the context..
What did I do wrong?
I am not sure at all that your EXEC_BAD_ACCESS depends on your callback. Indeed, if you say that it is called (I suppose you see the log) and since it only logs a message, there should be no problem with this.
EXEC_BAD_ACCESS is caused by an attempt to access an already deallocated object. You can get more information in two ways:
execute the program in debug mode, so when it crashes you will be able to see the stack content;
activate NSZombies or run the program using the performance tool Zombies; this will tell you exactly which object was accessed after its deallocation.
I know how to fix this. When calling this:
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
You don't include the code for the creation/type of the value called report. However the method name "Handle_IOHIDDeviceIOHIDReportCallback" comes from an Apple document where there is an error in the creation of the report value. https://developer.apple.com/library/archive/technotes/tn2187/_index.html
CFIndex reportSize = 64;
uint8_t report = malloc( reportSize ); // <---- WRONG
IOHIDDeviceRegisterInputReportCallback( deviceRef,
report,
reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,
context );
Instead do this:
uint8_t *report = (uint8_t *)malloc(reportSize);