Passing a 64bit value (a handle to plugin area) in current 4D Plugin SDK

Product :4D - 4D Server
I am converting my in house plug-ins to 64 bit for use in 4D v18. I use plug-in areas on forms their associated data structures. For sake of illustration I’ll say I have a plug-in area variable named ‘vlMyPlugInArea’ which is declared in 4D as a 32 bit longint in v15 and earlier. Viewed in the 4D debugger vlMyPlugInArea contains the handle address of the private data associated with the plug-in area. This is the same handle value which is set within the SDK by a call to ‘PA_SetAreareference’. There are many calls I make to the private data without plug-in area events triggering the calls. My current code just passes the private data handle value by passing vlMyPlugInArea as a PA_long32 which the 4D compiler recognizes by declaring the plug-in method parameters with ‘&L’. Example: MDC_ReturnATextFromPluginAreaData(&L):&T. I assume that in the 64bit world of v18 I will have to accommodate the use of 64 bit plug-in area handles, but there is no way to properly declare and pass a 64bit value using the most current 4D SDK I can find on line. I don’t want to rewrite my hundreds of plug-in calls which currently pass the plug-in area private data handle. Am I missing something or does the SDK (and possibly the 4D compiler) need to be updated to allow 64 bit values to be passed (&LL)?

Hi Marc,

C_LONGINT64 would be nice … maybe v19 :wink:

Without support for long64 in 4D, you can return a 64-bit address as a hexadecimal string, e.g. “‭7C42042C242C2424‬”.

I recently had a similar situation where I didn’t want to change the data type that was being passed between 4D and a plugin. So rather than worry about returning a 64-bit address to 4D I created a std::vector that stores the pointers to the data and returns the index into the vector as a 32-bit int. Then on calls into the plugin I resolve the data pointer from the vector using the index passed in.

There is a small amount of extra overhead in maintaining the vector, like having to make sure to set the address to null in the vector when the data is deleted and check for null before attempting to use a pointer, but it worked out a lot better for me than changing the data type. It also made it easier to handle the case where a call is made to the plugin with a data handle that has been deleted.


I really appreciate the input and it runs pretty close to different scenarios I have been considering. Using a hexadecimal string (or a blob as an alternative) will still mean rewriting the hundreds of calls within the 4D code since I’m currently passing the plugin area variable’s value (the handle to the private data) as a 32 bit value.

If a 64 bit handle will truncate in a reproducible manner when passed as a 32 bit value and you were using it as a “look-up” value in a two dimensional std::vector storing the truncated value next to the complete handle, it would be a reasonable way of going about it without changing the current 4D code calling the plugin method. I can see a way of constructing the two associated values during the eAE_InitAdvancedProperties plugin event by truncating the handle which 4D passed during that call. What I don’t know for sure is (1) whether the 4D compiler will complain about passing the plugin variable value in v18 (a 64 bit handle and a ‘&L’ declaration) and (2) if the truncated value passed by 4D will remain stable or if it will be “rounded” in a variable way as in when a 64 bit value is placed in a variable of type float.

I wanted to ask all of these questions at the Paris summit which just got cancelled. I’m hoping that someone at 4D will note the post and be able to supply some “guaranteed” answers.

Stay safe in our current COVID-19 world,


Hi Marc,

Not a problem. 4D use hex strings as node references with the XML


If a 64 bit handle will truncate in a reproducible manner when passed
as a 32 bit value

Truncating an 8 byte into a 4 byte value will just remove 4 of the bytes, so I’d be wary of using it as a lookup.
Consider this,
Code :
long l64_1 = 0x000000AAAAAAAAAA;
long l64_2 = 0x00000000AAAAAAAA;

int l32_1 = l64_1;
int l32_2 = l64_2;

std::cout << l32_1 << ‘\n’;
std::cout << l32_2 << ‘\n’;
The 64 bit handles are different but they truncated to the same 32 bit value.

Here’s a very rough example of what I did. I didn’t use void* though, I used std::shared_ptr.

Code :
std::vector<void*> handles;

size_t add_handle(void* h) {
return handles.size() - 1;

void* get_handle(size_t i) {
if (i < handles.size()) {
return handles;
return NULL;

void remove_handle(size_t i) {
if (i < handles.size()) {
handles = NULL;

It’s a shame that the summit had to be cancelled, but I’m not surprised. It’s a crazy time right now. Stay safe.

Hi Marc,

for our plugins we are using an internal mapping table. So internally we are using void* and we are passing a C_LONGINT starting with the number 1. Of course, you have always to convert the number into your internal pointer with every access. A further benefit is, that you can validate the input and the user cannot pass invalid pointers.