Passing a C struct to ChaiScript


#1

I’ve just started using ChaiScript and I’m having some issues with my code.

Currently I have a C++ application which as part of its usage, invokes GetThreadContext requests to keep tabs on a child thread. This works perfectly in when processing in C++ the returned CONTEXT C struct, I can retrieve it’s members like threadContext.ESP without problems.

However when I pass the CONTEXT struct to ChaiScript, I get the following error

CONTEXT threadContext;
GetThreadContext(myThread, &threadContext);

chai.add(chaiscript::var(threadContext), "thread_context");
chai.eval("print(thread_context.ESP)");

Error: “‘ESP’ is not a function.” during evaluation at (EVAL 1, 8)

Am I passing it, or referencing it incorrectly? Or is it something else entirely


#2

did you bind CONTEXT? if so can you post the code?
If not check out the docs for adding stuff to ChaiScript, especially read the part “Adding Functions”.
https://codedocs.xyz/ChaiScript/ChaiScript/index.html#adding_items

If you need help with writing the bindings, post declaration of CONTEXT.


#3

I guess this is why I wanted to highlight the importance of it being a C struct, and also not one I explicitly define. This is a Windows specific (as in literally defined inside winnt.h) structure that will vary depending on the CPU arch it is being compiled to. As in, when compiled for x86 will have the 32-bit registers EAX,EBX… defined as values in the structure, but x86-64 will have RAX,RBX… values.

Being a C struct, I do not have explicit control over the constructor/modifiers of this structure (nor would I want to, I make an API call GetThreadContext, and then I just want to run a script that can read the values of the struct it returns) but also there aren’t any methods for getters/setters, it’s just a bunch of values with names on them.

If I absolutely HAVE to define the structure in my own code and then make bindings for it, how would you suggest I might be able to read the values of a struct like this, if it were passed into my ChaiScript eval?

typedef struct _CONTEXT {
  DWORD ContextFlags;
  DWORD Dr0;
  DWORD Dr1;
  DWORD Dr2;
  DWORD Dr3;
  DWORD Dr6;
  DWORD Dr7;
  FLOATING_SAVE_AREA FloatSave;
  DWORD SegGs;
  DWORD SegFs;
  DWORD SegEs;
  DWORD SegDs;

  DWORD Edi;
  DWORD Esi;
  DWORD Ebx;
  DWORD Edx;
  DWORD Ecx;
  DWORD Eax;
  DWORD Ebp;
  DWORD Eip;
  DWORD SegCs;
  DWORD EFlags;
  DWORD Esp;
  DWORD SegSs;
  BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;

typedef CONTEXT *PCONTEXT;

#4

To bind eax in c++ do:

chai.add(fun(&CONTEXT::Eax), "Eax");

then in script:

print(thread_context.Eax.to_string());

If CONTEXT is dependent on ARCH, i fear you might have to replicate that using similar macros for you binding. As in

#ifdef SOME_ARCH_DEPENDENT_MACRO
// bind all the stuff that winnt.h would add to CONTEXT in this case
#else
...
#endif

Apart from that it might be advisable to:

chai.add(user_type<CONTEXT>(), "CONTEXT");

So ChaiScript has a proper name for your type.

PS: Being a C-Struct or being defined where-ever doesn’t matter as long as the proper header, winnt.h in this case, is included. You do not have to redeclare it or anything. Just have bindings for everything (member-vars,member-functions, constructors…) you want to use.