Advertisement
adilima

Objective-C Runtime Object Using MSVC

Oct 25th, 2012
335
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.34 KB | None | 0 0
  1. /***
  2.  * File: StrBuff.c
  3.  * AUTHOR:  FX. J. Adi Lima ( adi7598@gmail.com )
  4.  * DESCRIPTION:
  5.  *      A simple implementation of MSVC DLL which link against GNU libobjc.
  6.  *      This module implements a simple StringBuffer object, creatable from Objective-C.
  7.  *      The resulting Objective-C interface should be:
  8.  *
  9.  *      // typedef for Range (unsigned __int64)
  10.  *      typedef unsigned __int64 Range;
  11.  *      #define MakeRange(vStart, vEnd) (Range)(((Range)(vEnd) << 32) | (vEnd & 0xFFFFFFFF))
  12.  *      @interface StringBuffer {
  13.  *          Class isa;
  14.  *      }
  15.  *      + stringWithString:(id)aString;
  16.  *      + stringWithFormat:(LPCWSTR)pszFormat, ...;
  17.  *      - retain;
  18.  *      - (void) release;
  19.  *      - (LPCWSTR) string;
  20.  *      - (UINT) length;
  21.  *      - (StringBuffer*) description;
  22.  *      - (LPCWSTR) concatW:(LPCWSTR)pszFormat, ...;
  23.  *      - (StringBuffer*) substringFromRange:(Range)range;
  24.  *      @end
  25.  *
  26.  *      // You should also define the following
  27.  *      __inline LPCSTR __objc_class_name_StringBuffer() { return "StringBuffer"; }
  28.  *
  29.  *      // And use the StringBuffer object like normal.
  30.  *      // Ah, yes... please load the DLL first!!! (and free it when done)
  31. */
  32.  
  33. #include <windows.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stdarg.h>
  37. #include <string.h>
  38.  
  39. HINSTANCE hDllInstance = NULL;
  40. HINSTANCE hObjc = NULL;
  41.  
  42. typedef struct objc_class *Class;
  43. typedef struct objc_object *id;
  44. typedef struct objc_selector *SEL;
  45. typedef struct objc_protocol *Protocol;
  46.  
  47. struct objc_class { Class isa; };
  48. struct objc_object { Class isa; };
  49. typedef id (*IMP)(id _self, SEL _cmd, ...);
  50.  
  51. id (*objc_getClass)(LPCSTR) = NULL;
  52. id (*objc_allocateClassPair)(Class, LPCSTR, size_t) = NULL;
  53. void (*objc_registerClassPair)(Class) = NULL;
  54. Protocol (*objc_getProtocol)(LPCSTR) = NULL;
  55.  
  56. LPCSTR (*class_getName)(Class) = NULL;
  57. int (*class_addMethod)(Class, SEL, IMP, LPCSTR) = NULL;
  58. int (*class_addIvar)(Class, LPCSTR, size_t, BYTE, LPCSTR) = NULL;
  59. IMP (*class_getMethodImplementation)(Class, SEL) = NULL;
  60.  
  61. SEL (*selector)(LPCSTR) = NULL;
  62. LPCSTR (*selectorName)(SEL) = NULL;
  63. BOOL (*selectorEqual)(SEL, SEL) = NULL;
  64.  
  65. static int LoadFunctions(FARPROC* buffer, LPCSTR pszFirst, ...)
  66. {
  67.     FARPROC* pp = buffer;
  68.     LPCSTR psz = pszFirst;
  69.     int nRes = 0;
  70.     va_list args;
  71.     va_start(args, pszFirst);
  72.     while (psz)
  73.     {
  74.         *pp = GetProcAddress(hObjc, psz);
  75.         if (*pp) ++nRes;
  76.         pp++;
  77.         psz = va_arg(args, LPCSTR);
  78.     }
  79.     return nRes;
  80. }
  81.  
  82. BYTE log2Of(size_t ilen)
  83. {
  84.     size_t n = ilen;
  85.     BYTE ret = 0;
  86.     while ((n >>= 1) != 0) ++ret;
  87.     return ret;
  88. }
  89.  
  90. typedef struct CSTR {
  91.     Class isa;
  92.     LPCSTR pszText;
  93.     UINT length;
  94. } CSTR;
  95.  
  96. static Class __stringBufferClass = NULL;
  97. typedef unsigned __int64 UInt64;
  98.  
  99. typedef struct __GFSTRING {
  100.     Class isa;
  101.     LPWSTR lpw;
  102.     size_t length;
  103.     DWORD dwRef;
  104. } GFSTRING, *LPGFSTRING;
  105.  
  106. static Class GFStringInitialize(Class cls);
  107. static LPGFSTRING GFStringCreateWithString(Class cls, SEL _cmd, CSTR* pStr);
  108. static LPGFSTRING GFStringCreateWithFormat(Class cls, SEL _cmd, LPCWSTR pszFormat, ...);
  109. static LPGFSTRING GFStringRetain(LPGFSTRING pThis);
  110. static void GFStringRelease(LPGFSTRING pThis);
  111. static LPCWSTR GFStringGetString(LPGFSTRING pThis);
  112. static UINT GFStringGetLength(LPGFSTRING pThis);
  113. static LPGFSTRING GFStringGetDescription(LPGFSTRING pThis);
  114. static LPCWSTR GFStringConcatW(LPGFSTRING pThis, SEL _cmd, LPCWSTR pszFormat, ...);
  115. static LPGFSTRING GFStringSubstringFromRange(LPGFSTRING pThis, SEL _cmd, UInt64 range);
  116.  
  117. static BOOL GFStringRegisterClass(void)
  118. {
  119.     Class c = (Class)objc_allocateClassPair(NULL, "StringBuffer", 0);
  120.     if (!c) return FALSE;
  121.     class_addIvar(c, "isa", sizeof(Class), log2Of(sizeof(Class)), "#");
  122.     class_addMethod(c->isa, selector("initialize"), (IMP)GFStringInitialize, "##");
  123.     class_addMethod(c->isa, selector("stringWithString:"), (IMP)GFStringCreateWithString, "@#:@");
  124.     class_addMethod(c, selector("stringWithFormat:"), (IMP)GFStringCreateWithFormat, "@#:*");
  125.     class_addMethod(c, selector("retain"), (IMP)GFStringRetain, "@@:");
  126.     class_addMethod(c, selector("release"), (IMP)GFStringRelease, "v@:");
  127.     class_addMethod(c, selector("string"), (IMP)GFStringGetString, "*@:");
  128.     class_addMethod(c, selector("length"), (IMP)GFStringGetLength, "I@:");
  129.     class_addMethod(c, selector("description"), (IMP)GFStringGetDescription, "@@:");
  130.     class_addMethod(c, selector("concatW:"), (IMP)GFStringConcatW, "*@:*");
  131.     class_addMethod(c, selector("substringFromRange:"), (IMP)GFStringSubstringFromRange, "@@:Q");
  132.     objc_registerClassPair(c);
  133.     __stringBufferClass = c;
  134.     return TRUE;
  135. }
  136.  
  137. BOOL DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  138. {
  139.     if (dwReason == DLL_PROCESS_ATTACH)
  140.     {
  141.         hDllInstance = hInstance;
  142.         /* the following hardcoded path should be replaced according to what you need */
  143.         if (hObjc = LoadLibrary(L"E:\\mingw64\\bin\\libobjc-4.dll"))
  144.         {
  145.             FARPROC buffer[10];
  146.             int nRes = LoadFunctions(buffer, "objc_getClass", "objc_allocateClassPair",
  147.                 "objc_registerClassPair", "objc_getProtocol", NULL);
  148.             if (!nRes) return FALSE;
  149.             objc_getClass = (id (*)(LPCSTR))buffer[0];
  150.             objc_allocateClassPair = (id (*)(Class, LPCSTR, size_t))buffer[1];
  151.             objc_registerClassPair = (void (*)(Class))buffer[2];
  152.             objc_getProtocol = (Protocol (*)(LPCSTR))buffer[3];
  153.             nRes = LoadFunctions(buffer, "class_getName", "class_addMethod", "class_addIvar", "class_getMethodImplementation", NULL);
  154.             if (!nRes) return FALSE;
  155.             class_getName = (LPCSTR(*)(Class))buffer[0];
  156.             class_addMethod = (int(*)(Class, SEL, IMP, LPCSTR))buffer[1];
  157.             class_addIvar = (int(*)(Class, LPCSTR, size_t, BYTE, LPCSTR))buffer[2];
  158.             class_getMethodImplementation = (IMP(*)(Class, SEL))buffer[3];
  159.             nRes = LoadFunctions(buffer, "sel_registerName", "sel_getName", "sel_isEqual", NULL);
  160.             if (!nRes) return FALSE;
  161.             selector = (SEL(*)(LPCSTR))buffer[0];
  162.             selectorName = (LPCSTR(*)(SEL))buffer[1];
  163.             selectorEqual = (BOOL(*)(SEL, SEL))buffer[2];          
  164.             return GFStringRegisterClass();
  165.         }
  166.         return FALSE;
  167.     }
  168.     else if (dwReason == DLL_PROCESS_DETACH)
  169.     {
  170.         if (hObjc)
  171.         {
  172.             FreeLibrary(hObjc);
  173.             hObjc = NULL;
  174.         }
  175.     }
  176.     return TRUE;
  177. }
  178.  
  179. static Class GFStringInitialize(Class cls) {
  180.     return cls;
  181. }
  182.  
  183. static LPGFSTRING GFStringCreateWithString(Class cls, SEL _cmd, CSTR* pStr) {
  184.     LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  185.     size_t len = 0;
  186.     memset(pObj, 0, sizeof(GFSTRING));
  187.     pObj->isa = cls;
  188.     len = MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
  189.         NULL, 0) ;
  190.     pObj->lpw = (LPWSTR)malloc(sizeof(wchar_t) * len);
  191.     pObj->lpw[len-1] = 0;
  192.     MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
  193.         pObj->lpw, len);
  194.     pObj->dwRef = 1;
  195.     pObj->length = len;
  196.     return pObj;
  197. }
  198.  
  199. static LPGFSTRING GFStringCreateWithFormat(Class cls, SEL _cmd, LPCWSTR pszFormat, ...) {
  200.     LPWSTR temp = NULL;
  201.     size_t len = 0;
  202.     va_list args;
  203.     LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  204.     memset(pObj, 0, sizeof(GFSTRING));
  205.     pObj->isa = cls;
  206.    
  207.     va_start(args, pszFormat);
  208.     len = _vscwprintf(pszFormat, args) + 1;
  209.     temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
  210.     vswprintf_s(temp, len, pszFormat, args);
  211.     va_end(args);
  212.    
  213.     pObj->lpw = temp;
  214.     pObj->length = len;
  215.     pObj->dwRef = 1;
  216.     return pObj;
  217. }
  218.  
  219. static LPGFSTRING GFStringRetain(LPGFSTRING pThis) {
  220.     ++pThis->dwRef;
  221.     return pThis;
  222. }
  223.  
  224. static void GFStringRelease(LPGFSTRING pThis) {
  225.     if (--pThis->dwRef) return;
  226.     if (pThis->lpw) {
  227.         free(pThis->lpw);
  228.         pThis->lpw = NULL;
  229.         pThis->length = 0;
  230.     }
  231.     free((void*)pThis);
  232. }
  233.  
  234. static LPCWSTR GFStringGetString(LPGFSTRING pThis) {
  235.     return (LPCWSTR)pThis->lpw;
  236. }
  237.  
  238. static UINT GFStringGetLength(LPGFSTRING pThis) {
  239.     return (UINT)lstrlenW(pThis->lpw);
  240. }
  241.  
  242. static LPGFSTRING GFStringGetDescription(LPGFSTRING pThis) {
  243.     LPGFSTRING retVal = NULL;
  244.     LPWSTR lpw = NULL;
  245.     size_t len = lstrlenW(pThis->lpw) + 150;
  246.     lpw = (LPWSTR)malloc(sizeof(WCHAR) * len);
  247.     wsprintfW(lpw, L"<GFString 0x%p { string = %s, length = %lu }>",
  248.         pThis, pThis->lpw, pThis->length);
  249.     retVal = (LPGFSTRING)malloc(sizeof(GFSTRING));
  250.     retVal->isa = pThis->isa;
  251.     retVal->lpw = lpw;
  252.     retVal->length = len;
  253.     retVal->dwRef = 1;
  254.     return retVal;
  255. }
  256.  
  257. static LPCWSTR GFStringConcatW(LPGFSTRING pThis, SEL _cmd, LPCWSTR pszFormat, ...) {
  258.     LPWSTR lpw = NULL;
  259.     LPWSTR temp = NULL;
  260.     size_t len, total;
  261.     va_list args;
  262.     va_start(args, pszFormat);
  263.     len = _vscwprintf(pszFormat, args) + 1;
  264.     temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
  265.     vswprintf_s(temp, len, pszFormat, args);
  266.     va_end(args);
  267.     total = lstrlenW(pThis->lpw) + len;
  268.     lpw = (LPWSTR)malloc(sizeof(WCHAR) * total);
  269.     lstrcpyW(lpw, pThis->lpw);
  270.     lstrcatW(lpw, temp);
  271.     free(temp);
  272.     free(pThis->lpw);
  273.     pThis->lpw = lpw;
  274.     pThis->length = total;
  275.     return lpw;
  276. }
  277.  
  278. static LPGFSTRING GFStringSubstringFromRange(LPGFSTRING pThis, SEL _cmd, UInt64 range) {
  279.     LPGFSTRING pObj = NULL;
  280.     size_t nStart = (size_t)(range & 0xFFFFFFFF);
  281.     size_t nEnd = (size_t)((range >> 32) & 0xFFFFFFFF);
  282.     size_t total = nEnd - nStart;
  283.     size_t i;
  284.     LPWSTR p1, p2;
  285.    
  286.     if ((nEnd >= lstrlenW(pThis->lpw)) || (total > lstrlenW(pThis->lpw))) {
  287.         OutputDebugString(L"Invalid range specified!\n");
  288.         return NULL;
  289.     }
  290.     pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  291.     memset(pObj, 0, sizeof(GFSTRING));
  292.     pObj->isa = pThis->isa;
  293.     pObj->lpw = (LPWSTR)malloc(sizeof(WCHAR) * (total+1));
  294.     pObj->lpw[total] = 0;
  295.  
  296.     p1 = &pThis->lpw[nStart];
  297.     p2 = pObj->lpw;
  298.     for (i = 0; i < total; i++)
  299.         *p2++ = *p1++;
  300.    
  301.     pObj->length = lstrlenW(pObj->lpw);
  302.     pObj->dwRef = 1;
  303.     return pObj;
  304. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement