Jump to content

  • Log In with Google      Sign In   
  • Create Account


- - - - -

Problem: Attempting to pass around a void* as a handle within Angelscript.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 Magnitude   Members   -  Reputation: 103

Like
0Likes
Like

Posted 24 June 2013 - 04:27 PM

The Problem

I've attempted to register an object method ( asEngine_RegisterObjectMethod ) that takes in a GlobalData* and a uint, than returns a ref type.  Something about returning the ref however seems to cause the function to pass in an invalid pointer as the first parameter.  Modifying the function to return a non-generic type seems to correct the problem.

 

What I am trying to do -- Bigger Picture

I want to retrieve some data in the form of a void* and easily pass it around to various other bound functions.

In this simple example I want to retrieve a void* from an object as a generic handle, cast that handle, than pass that handle to another C-style function.

 

I want to able to return a void* as a ref ( or ref@, not sure since ref seems to be a special case), then cast that to a Entity@ and pass it along to a registered function that can take an Entity*.

 

I'd also like to avoid needing the user to register a cast function if they don't need to.  It seems like CScriptHandle can already be casted from one handle type to another.

 

This is ideally how I want the angelscript to look when the user attempts to get/pass around the data.

GLOBALDATA@ GlobalData = GetGlobalData();
ENTITY@ Entity = cast<ENTITY>(GlobalData.GetData( 2 ));
if( Entity !is null ){
    Entity_ProcessEntity( Entity );
}

I have registered the CScriptHandle type with the asEngine, however I seem to be missing something important during the implementation as things are not working as expected.

 

This is what the simplified C++ modules look like.

static class GlobalData
{
public:
   void* GetData( uint index ){ return _data[index]; }

private:
   void** _data[10];
} GlobalDataInstance;


//C-Style interface for GlobalData
GlobalData* GlobalData_GetGlobalData( void ){
    return &GlobalDataInstance;
}

void* GlobalData_GetData( GlobalData* globalData, uint index ){
   return globalData->GetData(index);
}

void Entity_ProcessEntity( Entity* entity ){
    entity->DoWork();
}

This is how they are registered with asEngine

Result = asEngine_RegisterGlobalFunction( Engine, "GLOBALDATA@ GetGlobalData()", asFUNCTION_t( &GlobalData_GetGlobalData), asCALL_CDECL );
Result = asEngine_RegisterObjectType( Engine, "GLOBALDATA", 0, asOBJ_REF | asOBJ_NOCOUNT );
Result = asEngine_RegisterObjectMethod( Engine, "GLOBALDATA",   "ref GetData( uint Index) const",  asFUNCTION_t(&GlobalData_GetData), asCALL_CDECL_OBJFIRST );

Result = asEngine_RegisterGlobalFunction( Engine, "void Entity_ProcessEntity( ENTITY@ entity)", asFUNCTION_t( &Entity_ProcessEntity), asCALL_CDECL );

asEngine_RegisterObjectMethod( Engine, "GLOBALDATA",   "ref GetData( uint Index) const",  asFUNCTION_t(&GlobalData_GetData), asCALL_CDECL_OBJFIRST );
This seems to be where the problem is occuring.  The GlobalData* provided here is not valid.  It is not null, however it is not GlobalDataInstance.

 

It could be that CScriptHandle is not the right solution for what i want to do, which is why I've included all of the additional information.

 

 



Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3261

Like
0Likes
Like

Posted 25 June 2013 - 11:36 AM

CScriptHandle is a C++ class and not a simple pointer. When you tell AngelScript that a function returns a "ref", then AngelScript will expect to receive a valid CScriptHandle object, but in your case you're just returning a void*. The calling convention for returning an object by value is different from the calling convention for returning a pointer. In the former a hidden pointer to a memory buffer is passed as the first argument to the function. This is why you see an invalid pointer.

 

If you want to use a completely generic pointer like void* in C/C++, then it would be best for you to register void* as a type itself. Then you can register your functions that take and receive void* using this type:

 

asEngine_RegisterObjectType(engine, "void_ptr", sizeof(void*), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
asEngine_RegisterObjectMethod( Engine, "GLOBALDATA",   "void_ptr GetData( uint Index) const",  asFUNCTION_t(&GlobalData_GetData), asCALL_CDECL_OBJFIRST );

 

As for casting the void_ptr into valid handles; I think it is best for you to create an appropriate function for this. If you do not want to have one function for each possible cast type, then I suggest you implement a function that takes a variable argument type, similar to the CScriptAny::Retrieve method. The problem is that the void* doesn't carry any information about the type of the object it points to, so I have no idea how you plan on validating if the cast is valid or not.


AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS