Newer
Older
Import / research / ui / toolkit / experiment / mac_introspection_test.cpp
#include "objc/runtime.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>


const char* decodeType(char* a_type)
{
  switch (a_type[0])
  {
    case 'c': return "char";
    case 'i': return "int";
    case 's': return "int16_t";
    case 'l': return "int32_t";
    case 'q': return "int64_t";
    case 'C': return "unsigned char";
    case 'I': return "unsigned int";
    case 'S': return "uint16_t";
    case 'L': return "uint32_t";
    case 'Q': return "uint64_t";
    case 'f': return "float";
    case 'd': return "double";
    case 'B': return "bool";
    case 'v': return "void";
    case '*': return "char*";
    case '@': return "id";
    case '#': return "Class";
    case ':': return "SEL";
    case '[': return "array";
    case '{': return "struct";
    case '(': return "union";
    case 'b': return "bitfield";
    case '^': return "pointer";
    case '?': return "misc";
  }
  return "unknown";
}


/*
// Wrapper idea - could do this for main ObjC classes
class NSWindow
{
public:
  NSWindow(double w, double h, unsigned windowFlags)
  {
    obj = ObjectiveC::Object("NSWindow")["alloc"]()["initWithContentRect:styleMask:backing:defer:"]((NSRect){ 0, 0, w, h }, windowFlags, 2, false);
  }
  inline void setContentView(id view) { obj["setContentView:"](view); }
  inline void becomeFirstResponder()  { obj["becomeFirstResponder"](); }
  inline void makeKeyAndOrderFront()  { obj["makeKeyAndOrderFront:"](obj.m_object); }
private:
  ObjectiveC::Object obj;
};
*/


int main()
{
  int classCount = objc_getClassList(nullptr, 0);
  Class* classList = new Class[classCount];
  classCount = objc_getClassList(classList, classCount);
 
  for (int i = 0; i < classCount; ++i)
  {
    const char* className = class_getName(classList[i]);
    if (className[0] == '_')
      continue;

    Class parentClass = class_getSuperclass(classList[i]);
    const char* parentClassName = class_getName(parentClass); 
    printf("class %s : public %s\n", className, parentClassName);
    printf("{\n");
    printf("public:\n");

    unsigned methodCount;
    Method* methods = class_copyMethodList(classList[i], &methodCount);
    for (unsigned m = 0; m < methodCount; ++m)
    {
      char* returnType = method_copyReturnType(methods[m]);
#if 1
      const char* methodName = sel_getName(method_getName(methods[m]));
      if (methodName[0] != '_')
      {
        //const char* methodTypeEncoding = method_getTypeEncoding(methods[m]);
        unsigned numberOfArguments = method_getNumberOfArguments(methods[m]);
       
        bool validMemberFunction = true;
        if (numberOfArguments < 2)
        {
          validMemberFunction = false;
        }
        else
        {
          char* argType = method_copyArgumentType(methods[m], 0);
          if (strcmp(decodeType(argType),"id"))
            validMemberFunction = false;
          free(argType);
          argType = method_copyArgumentType(methods[m], 1);
          if (strcmp(decodeType(argType),"SEL"))
            validMemberFunction = false;
          free(argType);
        }
        
        if (validMemberFunction)
        {
          //printf("  %s   ", methodTypeEncoding);
          printf("  inline %s %s(", decodeType(returnType), methodName);
          const char* varNames[] = { 0, 0, "a", "b", "c", "d", "e", "f", "g", "h" };
          for (unsigned arg = 2; arg < numberOfArguments; ++arg)
          {
            char* argType = method_copyArgumentType(methods[m], arg);
            printf("%s %s%s", decodeType(argType), varNames[arg], (arg != numberOfArguments - 1) ? "," : "");
            free(argType);
          }
          printf(")  {  obj[\"%s\"](", methodName);
          for (unsigned arg = 2; arg < numberOfArguments; ++arg)
          {
            printf("%s%s", varNames[arg], (arg != numberOfArguments - 1) ? "," : "");
          }
          printf(");  }\n");
        }
      }
#else
      objc_method_description* desc = method_getDescription(methods[m]);
      const char* methodName = sel_getName(desc->name);
      const char* methodTypeEncoding = desc->types;
      printf("  %s %s(%s);\n", returnType, methodName, methodTypeEncoding);
#endif
      free(returnType);
    }
    free(methods);

    
    printf("private:\n");
    printf("  ObjectiveC::Object obj;\n");
    printf("}\n");
  }
  return 1;
}