Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /***
- * File: StrBuff.c
- * AUTHOR: FX. J. Adi Lima ( adi7598@gmail.com )
- * DESCRIPTION:
- * A simple implementation of MSVC DLL which link against GNU libobjc.
- * This module implements a simple StringBuffer object, creatable from Objective-C.
- * The resulting Objective-C interface should be:
- *
- * // typedef for Range (unsigned __int64)
- * typedef unsigned __int64 Range;
- * #define MakeRange(vStart, vEnd) (Range)(((Range)(vEnd) << 32) | (vEnd & 0xFFFFFFFF))
- * @interface StringBuffer {
- * Class isa;
- * }
- * + stringWithString:(id)aString;
- * + stringWithFormat:(LPCWSTR)pszFormat, ...;
- * - retain;
- * - (void) release;
- * - (LPCWSTR) string;
- * - (UINT) length;
- * - (StringBuffer*) description;
- * - (LPCWSTR) concatW:(LPCWSTR)pszFormat, ...;
- * - (StringBuffer*) substringFromRange:(Range)range;
- * @end
- *
- * // You should also define the following
- * __inline LPCSTR __objc_class_name_StringBuffer() { return "StringBuffer"; }
- *
- * // And use the StringBuffer object like normal.
- * // Ah, yes... please load the DLL first!!! (and free it when done)
- */
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- HINSTANCE hDllInstance = NULL;
- HINSTANCE hObjc = NULL;
- typedef struct objc_class *Class;
- typedef struct objc_object *id;
- typedef struct objc_selector *SEL;
- typedef struct objc_protocol *Protocol;
- struct objc_class { Class isa; };
- struct objc_object { Class isa; };
- typedef id (*IMP)(id _self, SEL _cmd, ...);
- id (*objc_getClass)(LPCSTR) = NULL;
- id (*objc_allocateClassPair)(Class, LPCSTR, size_t) = NULL;
- void (*objc_registerClassPair)(Class) = NULL;
- Protocol (*objc_getProtocol)(LPCSTR) = NULL;
- LPCSTR (*class_getName)(Class) = NULL;
- int (*class_addMethod)(Class, SEL, IMP, LPCSTR) = NULL;
- int (*class_addIvar)(Class, LPCSTR, size_t, BYTE, LPCSTR) = NULL;
- IMP (*class_getMethodImplementation)(Class, SEL) = NULL;
- SEL (*selector)(LPCSTR) = NULL;
- LPCSTR (*selectorName)(SEL) = NULL;
- BOOL (*selectorEqual)(SEL, SEL) = NULL;
- static int LoadFunctions(FARPROC* buffer, LPCSTR pszFirst, ...)
- {
- FARPROC* pp = buffer;
- LPCSTR psz = pszFirst;
- int nRes = 0;
- va_list args;
- va_start(args, pszFirst);
- while (psz)
- {
- *pp = GetProcAddress(hObjc, psz);
- if (*pp) ++nRes;
- pp++;
- psz = va_arg(args, LPCSTR);
- }
- return nRes;
- }
- BYTE log2Of(size_t ilen)
- {
- size_t n = ilen;
- BYTE ret = 0;
- while ((n >>= 1) != 0) ++ret;
- return ret;
- }
- typedef struct CSTR {
- Class isa;
- LPCSTR pszText;
- UINT length;
- } CSTR;
- static Class __stringBufferClass = NULL;
- typedef unsigned __int64 UInt64;
- typedef struct __GFSTRING {
- Class isa;
- LPWSTR lpw;
- size_t length;
- DWORD dwRef;
- } GFSTRING, *LPGFSTRING;
- static Class GFStringInitialize(Class cls);
- static LPGFSTRING GFStringCreateWithString(Class cls, SEL _cmd, CSTR* pStr);
- static LPGFSTRING GFStringCreateWithFormat(Class cls, SEL _cmd, LPCWSTR pszFormat, ...);
- static LPGFSTRING GFStringRetain(LPGFSTRING pThis);
- static void GFStringRelease(LPGFSTRING pThis);
- static LPCWSTR GFStringGetString(LPGFSTRING pThis);
- static UINT GFStringGetLength(LPGFSTRING pThis);
- static LPGFSTRING GFStringGetDescription(LPGFSTRING pThis);
- static LPCWSTR GFStringConcatW(LPGFSTRING pThis, SEL _cmd, LPCWSTR pszFormat, ...);
- static LPGFSTRING GFStringSubstringFromRange(LPGFSTRING pThis, SEL _cmd, UInt64 range);
- static BOOL GFStringRegisterClass(void)
- {
- Class c = (Class)objc_allocateClassPair(NULL, "StringBuffer", 0);
- if (!c) return FALSE;
- class_addIvar(c, "isa", sizeof(Class), log2Of(sizeof(Class)), "#");
- class_addMethod(c->isa, selector("initialize"), (IMP)GFStringInitialize, "##");
- class_addMethod(c->isa, selector("stringWithString:"), (IMP)GFStringCreateWithString, "@#:@");
- class_addMethod(c, selector("stringWithFormat:"), (IMP)GFStringCreateWithFormat, "@#:*");
- class_addMethod(c, selector("retain"), (IMP)GFStringRetain, "@@:");
- class_addMethod(c, selector("release"), (IMP)GFStringRelease, "v@:");
- class_addMethod(c, selector("string"), (IMP)GFStringGetString, "*@:");
- class_addMethod(c, selector("length"), (IMP)GFStringGetLength, "I@:");
- class_addMethod(c, selector("description"), (IMP)GFStringGetDescription, "@@:");
- class_addMethod(c, selector("concatW:"), (IMP)GFStringConcatW, "*@:*");
- class_addMethod(c, selector("substringFromRange:"), (IMP)GFStringSubstringFromRange, "@@:Q");
- objc_registerClassPair(c);
- __stringBufferClass = c;
- return TRUE;
- }
- BOOL DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
- {
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- hDllInstance = hInstance;
- /* the following hardcoded path should be replaced according to what you need */
- if (hObjc = LoadLibrary(L"E:\\mingw64\\bin\\libobjc-4.dll"))
- {
- FARPROC buffer[10];
- int nRes = LoadFunctions(buffer, "objc_getClass", "objc_allocateClassPair",
- "objc_registerClassPair", "objc_getProtocol", NULL);
- if (!nRes) return FALSE;
- objc_getClass = (id (*)(LPCSTR))buffer[0];
- objc_allocateClassPair = (id (*)(Class, LPCSTR, size_t))buffer[1];
- objc_registerClassPair = (void (*)(Class))buffer[2];
- objc_getProtocol = (Protocol (*)(LPCSTR))buffer[3];
- nRes = LoadFunctions(buffer, "class_getName", "class_addMethod", "class_addIvar", "class_getMethodImplementation", NULL);
- if (!nRes) return FALSE;
- class_getName = (LPCSTR(*)(Class))buffer[0];
- class_addMethod = (int(*)(Class, SEL, IMP, LPCSTR))buffer[1];
- class_addIvar = (int(*)(Class, LPCSTR, size_t, BYTE, LPCSTR))buffer[2];
- class_getMethodImplementation = (IMP(*)(Class, SEL))buffer[3];
- nRes = LoadFunctions(buffer, "sel_registerName", "sel_getName", "sel_isEqual", NULL);
- if (!nRes) return FALSE;
- selector = (SEL(*)(LPCSTR))buffer[0];
- selectorName = (LPCSTR(*)(SEL))buffer[1];
- selectorEqual = (BOOL(*)(SEL, SEL))buffer[2];
- return GFStringRegisterClass();
- }
- return FALSE;
- }
- else if (dwReason == DLL_PROCESS_DETACH)
- {
- if (hObjc)
- {
- FreeLibrary(hObjc);
- hObjc = NULL;
- }
- }
- return TRUE;
- }
- static Class GFStringInitialize(Class cls) {
- return cls;
- }
- static LPGFSTRING GFStringCreateWithString(Class cls, SEL _cmd, CSTR* pStr) {
- LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
- size_t len = 0;
- memset(pObj, 0, sizeof(GFSTRING));
- pObj->isa = cls;
- len = MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
- NULL, 0) ;
- pObj->lpw = (LPWSTR)malloc(sizeof(wchar_t) * len);
- pObj->lpw[len-1] = 0;
- MultiByteToWideChar(CP_UTF8, 0, pStr->pszText, lstrlenA(pStr->pszText),
- pObj->lpw, len);
- pObj->dwRef = 1;
- pObj->length = len;
- return pObj;
- }
- static LPGFSTRING GFStringCreateWithFormat(Class cls, SEL _cmd, LPCWSTR pszFormat, ...) {
- LPWSTR temp = NULL;
- size_t len = 0;
- va_list args;
- LPGFSTRING pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
- memset(pObj, 0, sizeof(GFSTRING));
- pObj->isa = cls;
- va_start(args, pszFormat);
- len = _vscwprintf(pszFormat, args) + 1;
- temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
- vswprintf_s(temp, len, pszFormat, args);
- va_end(args);
- pObj->lpw = temp;
- pObj->length = len;
- pObj->dwRef = 1;
- return pObj;
- }
- static LPGFSTRING GFStringRetain(LPGFSTRING pThis) {
- ++pThis->dwRef;
- return pThis;
- }
- static void GFStringRelease(LPGFSTRING pThis) {
- if (--pThis->dwRef) return;
- if (pThis->lpw) {
- free(pThis->lpw);
- pThis->lpw = NULL;
- pThis->length = 0;
- }
- free((void*)pThis);
- }
- static LPCWSTR GFStringGetString(LPGFSTRING pThis) {
- return (LPCWSTR)pThis->lpw;
- }
- static UINT GFStringGetLength(LPGFSTRING pThis) {
- return (UINT)lstrlenW(pThis->lpw);
- }
- static LPGFSTRING GFStringGetDescription(LPGFSTRING pThis) {
- LPGFSTRING retVal = NULL;
- LPWSTR lpw = NULL;
- size_t len = lstrlenW(pThis->lpw) + 150;
- lpw = (LPWSTR)malloc(sizeof(WCHAR) * len);
- wsprintfW(lpw, L"<GFString 0x%p { string = %s, length = %lu }>",
- pThis, pThis->lpw, pThis->length);
- retVal = (LPGFSTRING)malloc(sizeof(GFSTRING));
- retVal->isa = pThis->isa;
- retVal->lpw = lpw;
- retVal->length = len;
- retVal->dwRef = 1;
- return retVal;
- }
- static LPCWSTR GFStringConcatW(LPGFSTRING pThis, SEL _cmd, LPCWSTR pszFormat, ...) {
- LPWSTR lpw = NULL;
- LPWSTR temp = NULL;
- size_t len, total;
- va_list args;
- va_start(args, pszFormat);
- len = _vscwprintf(pszFormat, args) + 1;
- temp = (LPWSTR)malloc(sizeof(WCHAR) * len);
- vswprintf_s(temp, len, pszFormat, args);
- va_end(args);
- total = lstrlenW(pThis->lpw) + len;
- lpw = (LPWSTR)malloc(sizeof(WCHAR) * total);
- lstrcpyW(lpw, pThis->lpw);
- lstrcatW(lpw, temp);
- free(temp);
- free(pThis->lpw);
- pThis->lpw = lpw;
- pThis->length = total;
- return lpw;
- }
- static LPGFSTRING GFStringSubstringFromRange(LPGFSTRING pThis, SEL _cmd, UInt64 range) {
- LPGFSTRING pObj = NULL;
- size_t nStart = (size_t)(range & 0xFFFFFFFF);
- size_t nEnd = (size_t)((range >> 32) & 0xFFFFFFFF);
- size_t total = nEnd - nStart;
- size_t i;
- LPWSTR p1, p2;
- if ((nEnd >= lstrlenW(pThis->lpw)) || (total > lstrlenW(pThis->lpw))) {
- OutputDebugString(L"Invalid range specified!\n");
- return NULL;
- }
- pObj = (LPGFSTRING)malloc(sizeof(GFSTRING));
- memset(pObj, 0, sizeof(GFSTRING));
- pObj->isa = pThis->isa;
- pObj->lpw = (LPWSTR)malloc(sizeof(WCHAR) * (total+1));
- pObj->lpw[total] = 0;
- p1 = &pThis->lpw[nStart];
- p2 = pObj->lpw;
- for (i = 0; i < total; i++)
- *p2++ = *p1++;
- pObj->length = lstrlenW(pObj->lpw);
- pObj->dwRef = 1;
- return pObj;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement