Advertisement
adilima

Objective-C Runtime Object Using MSVC (More usable example)

Oct 25th, 2012
352
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. static WCHAR GFStringGetCharAtIndex(LPGFSTRING pThis, SEL _Cmd, int index);
  117. static UINT GFStringGetFirstIndexOfChar(LPGFSTRING pThis, SEL _cmd, wchar_t chVal);
  118. static UINT GFStringGetLastIndexOfChar(LPGFSTRING pThis, SEL _cmd, wchar_t chVal);
  119.  
  120. static BOOL GFStringRegisterClass(void)
  121. {
  122.     Class c = (Class)objc_allocateClassPair(NULL, "StringBuffer", 0);
  123.     if (!c) return FALSE;
  124.     class_addIvar(c, "isa", sizeof(Class), log2Of(sizeof(Class)), "#");
  125.     class_addMethod(c->isa, selector("initialize"), (IMP)GFStringInitialize, "##");
  126.     class_addMethod(c->isa, selector("stringWithString:"), (IMP)GFStringCreateWithString, "@#:@");
  127.     class_addMethod(c, selector("stringWithFormat:"), (IMP)GFStringCreateWithFormat, "@#:*");
  128.     class_addMethod(c, selector("retain"), (IMP)GFStringRetain, "@@:");
  129.     class_addMethod(c, selector("release"), (IMP)GFStringRelease, "v@:");
  130.     class_addMethod(c, selector("string"), (IMP)GFStringGetString, "*@:");
  131.     class_addMethod(c, selector("length"), (IMP)GFStringGetLength, "I@:");
  132.     class_addMethod(c, selector("description"), (IMP)GFStringGetDescription, "@@:");
  133.     class_addMethod(c, selector("concatW:"), (IMP)GFStringConcatW, "*@:*");
  134.     class_addMethod(c, selector("substringFromRange:"), (IMP)GFStringSubstringFromRange, "@@:Q");
  135.     class_addMethod(c, selector("characterAtIndex:"), (IMP)GFStringGetCharAtIndex, "S@:I");
  136.     class_addMethod(c, selector("firstIndexOf:"), (IMP)GFStringGetFirstIndexOfChar, "I@:S");
  137.     class_addMethod(c, selector("lastIndexOf:"), (IMP)GFStringGetLastIndexOfChar, "I@:S");
  138.     objc_registerClassPair(c);
  139.     __stringBufferClass = c;
  140.     return TRUE;
  141. }
  142.  
  143. BOOL DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  144. {
  145.     if (dwReason == DLL_PROCESS_ATTACH)
  146.     {
  147.         hDllInstance = hInstance;
  148.         /* the following hardcoded path should be replaced according to what you need */
  149.         if (hObjc = LoadLibrary(L"E:\\mingw64\\bin\\libobjc-4.dll"))
  150.         {
  151.             FARPROC buffer[10];
  152.             int nRes = LoadFunctions(buffer, "objc_getClass", "objc_allocateClassPair",
  153.                 "objc_registerClassPair", "objc_getProtocol", NULL);
  154.             if (!nRes) return FALSE;
  155.             objc_getClass = (id (*)(LPCSTR))buffer[0];
  156.             objc_allocateClassPair = (id (*)(Class, LPCSTR, size_t))buffer[1];
  157.             objc_registerClassPair = (void (*)(Class))buffer[2];
  158.             objc_getProtocol = (Protocol (*)(LPCSTR))buffer[3];
  159.             nRes = LoadFunctions(buffer, "class_getName", "class_addMethod", "class_addIvar", "class_getMethodImplementation", NULL);
  160.             if (!nRes) return FALSE;
  161.             class_getName = (LPCSTR(*)(Class))buffer[0];
  162.             class_addMethod = (int(*)(Class, SEL, IMP, LPCSTR))buffer[1];
  163.             class_addIvar = (int(*)(Class, LPCSTR, size_t, BYTE, LPCSTR))buffer[2];
  164.             class_getMethodImplementation = (IMP(*)(Class, SEL))buffer[3];
  165.             nRes = LoadFunctions(buffer, "sel_registerName", "sel_getName", "sel_isEqual", NULL);
  166.             if (!nRes) return FALSE;
  167.             selector = (SEL(*)(LPCSTR))buffer[0];
  168.             selectorName = (LPCSTR(*)(SEL))buffer[1];
  169.             selectorEqual = (BOOL(*)(SEL, SEL))buffer[2];          
  170.             return GFStringRegisterClass();
  171.         }
  172.         return FALSE;
  173.     }
  174.     else if (dwReason == DLL_PROCESS_DETACH)
  175.     {
  176.         if (hObjc)
  177.         {
  178.             FreeLibrary(hObjc);
  179.             hObjc = NULL;
  180.         }
  181.     }
  182.     return TRUE;
  183. }
  184.  
  185. static Class GFStringInitialize(Class cls) {
  186.     return cls;
  187. }
  188.  
  189. static LPGFSTRING GFStringCreateWithString(Class cls, SEL _cmd, CSTR* pStr) {
  190.     LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  191.     size_t len = 0;
  192.     memset(pObj, 0, sizeof(GFSTRING));
  193.     pObj->isa = cls;
  194.     len = MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
  195.         NULL, 0) ;
  196.     pObj->lpw = (LPWSTR)malloc(sizeof(wchar_t) * len);
  197.     pObj->lpw[len-1] = 0;
  198.     MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
  199.         pObj->lpw, len);
  200.     pObj->dwRef = 1;
  201.     pObj->length = len;
  202.     return pObj;
  203. }
  204.  
  205. static LPGFSTRING GFStringCreateWithFormat(Class cls, SEL _cmd, LPCWSTR pszFormat, ...) {
  206.     LPWSTR temp = NULL;
  207.     size_t len = 0;
  208.     va_list args;
  209.     LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  210.     memset(pObj, 0, sizeof(GFSTRING));
  211.     pObj->isa = cls;
  212.    
  213.     va_start(args, pszFormat);
  214.     len = _vscwprintf(pszFormat, args) + 1;
  215.     temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
  216.     vswprintf_s(temp, len, pszFormat, args);
  217.     va_end(args);
  218.    
  219.     pObj->lpw = temp;
  220.     pObj->length = len;
  221.     pObj->dwRef = 1;
  222.     return pObj;
  223. }
  224.  
  225. static LPGFSTRING GFStringRetain(LPGFSTRING pThis) {
  226.     ++pThis->dwRef;
  227.     return pThis;
  228. }
  229.  
  230. static void GFStringRelease(LPGFSTRING pThis) {
  231.     if (--pThis->dwRef) return;
  232.     if (pThis->lpw) {
  233.         free(pThis->lpw);
  234.         pThis->lpw = NULL;
  235.         pThis->length = 0;
  236.     }
  237.     free((void*)pThis);
  238. }
  239.  
  240. static LPCWSTR GFStringGetString(LPGFSTRING pThis) {
  241.     return (LPCWSTR)pThis->lpw;
  242. }
  243.  
  244. static UINT GFStringGetLength(LPGFSTRING pThis) {
  245.     return (UINT)lstrlenW(pThis->lpw);
  246. }
  247.  
  248. static LPGFSTRING GFStringGetDescription(LPGFSTRING pThis) {
  249.     LPGFSTRING retVal = NULL;
  250.     LPWSTR lpw = NULL;
  251.     size_t len = lstrlenW(pThis->lpw) + 150;
  252.     lpw = (LPWSTR)malloc(sizeof(WCHAR) * len);
  253.     wsprintfW(lpw, L"<GFString 0x%p { string = %s, length = %lu }>",
  254.         pThis, pThis->lpw, pThis->length);
  255.     retVal = (LPGFSTRING)malloc(sizeof(GFSTRING));
  256.     retVal->isa = pThis->isa;
  257.     retVal->lpw = lpw;
  258.     retVal->length = len;
  259.     retVal->dwRef = 1;
  260.     return retVal;
  261. }
  262.  
  263. static LPCWSTR GFStringConcatW(LPGFSTRING pThis, SEL _cmd, LPCWSTR pszFormat, ...) {
  264.     LPWSTR lpw = NULL;
  265.     LPWSTR temp = NULL;
  266.     size_t len, total;
  267.     va_list args;
  268.     va_start(args, pszFormat);
  269.     len = _vscwprintf(pszFormat, args) + 1;
  270.     temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
  271.     vswprintf_s(temp, len, pszFormat, args);
  272.     va_end(args);
  273.     total = lstrlenW(pThis->lpw) + len;
  274.     lpw = (LPWSTR)malloc(sizeof(WCHAR) * total);
  275.     lstrcpyW(lpw, pThis->lpw);
  276.     lstrcatW(lpw, temp);
  277.     free(temp);
  278.     free(pThis->lpw);
  279.     pThis->lpw = lpw;
  280.     pThis->length = total;
  281.     return lpw;
  282. }
  283.  
  284. static LPGFSTRING GFStringSubstringFromRange(LPGFSTRING pThis, SEL _cmd, UInt64 range) {
  285.     LPGFSTRING pObj = NULL;
  286.     size_t nStart = (size_t)(range & 0xFFFFFFFF);
  287.     size_t nEnd = (size_t)((range >> 32) & 0xFFFFFFFF);
  288.     size_t total = nEnd - nStart;
  289.     size_t i;
  290.     LPWSTR p1, p2;
  291.    
  292.     if ((nEnd >= lstrlenW(pThis->lpw)) || (total > lstrlenW(pThis->lpw))) {
  293.         OutputDebugString(L"Invalid range specified!\n");
  294.         return NULL;
  295.     }
  296.     pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
  297.     memset(pObj, 0, sizeof(GFSTRING));
  298.     pObj->isa = pThis->isa;
  299.     pObj->lpw = (LPWSTR)malloc(sizeof(WCHAR) * (total+1));
  300.     pObj->lpw[total] = 0;
  301.  
  302.     p1 = &pThis->lpw[nStart];
  303.     p2 = pObj->lpw;
  304.     for (i = 0; i < total; i++)
  305.         *p2++ = *p1++;
  306.    
  307.     pObj->length = lstrlenW(pObj->lpw);
  308.     pObj->dwRef = 1;
  309.     return pObj;
  310. }
  311.  
  312. static WCHAR GFStringGetCharAtIndex(LPGFSTRING pThis, SEL _Cmd, int index) {
  313.     if (pThis->lpw && (index < pThis->length))
  314.         return pThis->lpw[index];
  315.     return 0;
  316. }
  317.  
  318. static UINT GFStringGetFirstIndexOfChar(LPGFSTRING pThis, SEL _cmd, wchar_t chVal) {
  319.     if (pThis->lpw) {
  320.         size_t i = 0;
  321.         LPWSTR p = pThis->lpw;
  322.         while (i < pThis->length) {
  323.             if (*p == chVal) return (UINT)i;
  324.             i++;
  325.             p++;
  326.         }
  327.     }
  328.     /* not found */
  329.     return -1;
  330. }
  331.  
  332. static UINT GFStringGetLastIndexOfChar(LPGFSTRING pThis, SEL _cmd, wchar_t chVal) {
  333.     if (pThis->lpw) {
  334.         UINT i = (UINT)pThis->length - 1;
  335.         LPWSTR p = &pThis->lpw[i];
  336.         while (i >= 0) {
  337.             if (*p == chVal) return i;
  338.             --i;
  339.             --p;
  340.         }
  341.     }
  342.     return -1;
  343. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement