luajit中。利用ffi能够嵌入C。眼下luajit的最新版是2.0.4,在这之前的版本号我还不清楚这个扩展库详细怎么样,只是在2.04中,真的非常爽。



既然是嵌入C代码。那么要说让lua支持面向对象。不如说是让C语言模拟面向对象编程。然后让luajit的ffi嵌入。

要文字彻底来描写叙述清楚这个问题。我的表达能力非常有限,说不清楚,所以直接用代码来说吧。

//C++
class foo_type{
public:
void foo1()
{
printf("%d", a + b);
} void foo2(int n)
{
printf("%d", a + b + n);
}
int a;
int b;
}; foo_type obj;
obj.foo1();
obj.foo2(100); //在C语言要做到相同的事。最简单的做法例如以下。 typedef struct{
int a;
int b;
}foo_type;
void foo1(foo_type *obj)
{
printf("%d", obj->a + obj->y);
} void foo2(foo_type *obj, int n)
{
printf("%d", obj->a + obj->y + n);
} foo_type obj;
foo1(&obj);
foo2(&obj, 100); /*****************************************
//C++从汇编语言的角度看
obj.foo1();
lea ecx, obj
call foo1
----------------------- obj.foo2(100);
push 100
lea ecx, obj
call foo1
----------------------- //C语言从汇编语言的角度看
foo1(&obj);
lea eax, obj
push eax
call foo1
----------------------- foo2(&obj, 100);
push 100
lea eax, obj
push eax
call foo2 那么就能够看到,C和C++在实现这样的功能时的差别之处主要在于thiscall使用了ecx寄存器向下传递对象指针
而在C语言。仅仅能把结构指针push下去,这就有点像微软的COM包装类的stdcall的类成员了。 *****************************************/ //从汇编看到问题所在之后,要解决问题,也就在能够考虑写一个shellcode,这个shellcode实现将向下传递上层传入的參数。而且直接将结构指针以push參数的方式最后入栈。然后call就可以。
typedef struct{
int a;
int b;
}foo_type;
void foo1(foo_type *obj)
{
printf("%d", obj->a + obj->y);
} void foo2(foo_type *obj, int n)
{
printf("%d", obj->a + obj->y + n);
} typedef struct{
void (*foo1)();
void (*foo2)(int n);
}foo_class; foo_type ft;
foo_class obj;
//与foo1相应的shellcode模板
BYTE scT1[] = {
0x68, 0, 0, 0, 0, //push CONST
0xE8, 0, 0, 0, 0, //call CONST
0x83, 0xC4, 0x04, //add esp, 4
0xC3 //ret
}; BYTE *psc = (BYTE*)VirtualAlloc(NULL, sizeof(scT1), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(psc, scT1, sizeof(scT1));
*(ULONG*)(psc + 1) = (ULONG)&ft;
*(ULONG*)(psc + 6) = (ULONG)&foo1 - (ULONG)(psc + 5) - 5;
*(ULONG*)&(obj.foo1) = psc; //到这里之后,就已经能够这样用了
obj.foo1(); //与foo2相应的shellcode模板
BYTE scT2[] = {
0xFF, 0x74, 0x24, 0x04, //push dword ptr [esp + 4]
0x68, 0, 0, 0, 0, //call CONST
0xE8, 0, 0, 0, 0, //call CONST
0x83, 0xC4, 0x08, //add esp, 8
0xC3 //ret
};
BYTE *psc = (BYTE*)VirtualAlloc(NULL, sizeof(scT2), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(psc, scT2, sizeof(scT2));
*(ULONG*)(psc + 5) = (ULONG)&ft;
*(ULONG*)(psc + 10) = (ULONG)&foo2 - (ULONG)(psc + 5) - 5;
*(ULONG*)&(obj.foo2) = psc; obj.foo2(100); //这样就模拟了面向对象形式的调用,之后就须要考虑的就是一些怎样整合管理资源之类的问题,还须要将代码尽可能的利用一些宏来简化,这些东西就不在这里说了,这个思路深入下去。相信大家都会知道该怎么做了。

以下是一套我封装的luajit使用ODBC訪问数据库的代码,没有凝视。将就着看吧。

//luaodbc.h**************************************************
#pragma once extern "C"{
typedef struct{
void (*close)();
bool (*set)(int i, int type, char *data, int size);
bool (*get)(int i, int type);
void *(*data)();
bool (*next)();
char *(*getstr)(int i);
int (*getint)(int i);
char *(*getstr_fn)(const char *name);
char *(*getint_fn)(const char *name);
bool (*setstr)(int i, const char *str);
bool (*setint)(int i, int num);
bool (*setstr_fn)(const char *name, const char *str);
bool (*setint_fn)(const char *name, int num);
}luastmt_class; typedef struct{
bool (*open)(const char*dsn);
void (*close)();
luastmt_class *(*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
}luadbc_class; __declspec(dllexport) luadbc_class *luadbc_init();
__declspec(dllexport) void luadbc_exit(luadbc_class *obj);
}; //luaodbc.cpp**************************************************
#include "stdafx.h"
#include "luaodbc.h"
#include <sql.h>
#include <sqlext.h>
#include <list>
#include <algorithm>
#include <string> extern "C"{
#define LOS_CLOSED 0
#define LOS_INITILZED 1
#define LOS_CONNECTIONED 2
#define LOS_TRAN 4
#define LOS_STMTOPENED 8 typedef struct _ciType{
char name[68];
int type;
int type_len;
char *data;
int data_size;
int nds;
}ciType; typedef struct _stmtType{
SQLHANDLE hstmt;
ciType *cols;
int col_count;
int cp_size;
unsigned int status;
void *parent;
luastmt_class thisobj;
unsigned char *class_memory;
int gci;
_stmtType *next;
}stmtType; typedef struct{
int (*open)(const char*dsn);
void (*close)();
bool (*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
void *dbc_obj;
}luadbc_class_ex; typedef struct _odbcType{
SQLHANDLE henv, hdbc;
_stmtType *stmt_list;
unsigned int status;
luadbc_class_ex thisobj;
unsigned char *class_memory;
}odbcType; BYTE scT1[] = {
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x04,
0xC3
}; BYTE scT2[] = {
0xFF, 0x74, 0x24, 0x04,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x08,
0xC3
}; BYTE scT3[] = {
0xFF, 0x74, 0x24, 0x08,
0xFF, 0x74, 0x24, 0x08,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x0C,
0xC3
}; BYTE scT4[] = {
0xFF, 0x74, 0x24, 0x0C,
0xFF, 0x74, 0x24, 0x0C,
0xFF, 0x74, 0x24, 0x0C,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x10,
0xC3
}; BYTE scT5[] = {
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0xFF, 0x74, 0x24, 0x10,
0x68, 0, 0, 0, 0,
0xE8, 0, 0, 0, 0,
0x83, 0xC4, 0x14,
0xC3
}; #define SCTP1 1
#define SCTP2 SCTP1 + 4
#define SCTP3 SCTP2 + 4
#define SCTP4 SCTP3 + 4
#define SCTP5 SCTP4 + 4 std::list<int> g_safe_luaodbc_list;
CRITICAL_SECTION g_safe_luaodbc_cs;
class luaodbc_startup{
public:
luaodbc_startup()
{
InitializeCriticalSection(&g_safe_luaodbc_cs);
static_link = 1;
}
int static_link;
}; static luaodbc_startup g_luaodbc_link;
static int ___g_static_link = g_luaodbc_link.static_link; void luastmt_close(stmtType *v)
{
if(v->status & LOS_STMTOPENED)
{
SQLFreeHandle(SQL_HANDLE_STMT, v->hstmt);
v->hstmt = NULL;
v->status ^= LOS_STMTOPENED;
}
} void luaodbc_coldata_realloc(stmtType *v, int i, int size)
{
delete v->cols[i].data;
v->cols[i].data = new char[size];
} BOOL luastmt_set(stmtType *v, int i, int type, char *data, int size)
{
if(!data || i <= 0)
return FALSE;
if(!(v->status & LOS_STMTOPENED))
return FALSE;
SQLINTEGER ncb = size;
//printf("data:%s, i:%d, len:%d, type:%d\n", data,i, size, type);
SQLFreeStmt(v->hstmt, SQL_UNBIND);
SQLRETURN rc = SQLBindCol(v->hstmt, (SQLUSMALLINT)i, (SQLSMALLINT)type, (SQLPOINTER)data, (SQLINTEGER)size, &ncb);
if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
SQLSetPos(v->hstmt, 1, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
//printf("update:%d, %d\n", rc, ncb);
SQLFreeStmt(v->hstmt, SQL_UNBIND);
return TRUE;
} BOOL luastmt_get(stmtType *v, int i, int type)
{
if(i <= 0)
return FALSE;
if(!(v->status & LOS_STMTOPENED))
return FALSE;
SQLRETURN rc;
for(;;)
{
if(v->gci == i)
SQLSetPos(v->hstmt, 1, SQL_POSITION, SQL_LOCK_NO_CHANGE);
else
v->gci = i;
rc = SQLGetData(v->hstmt, i, type,
v->cols[i - 1].data, v->cols[i - 1].data_size, (SQLINTEGER*)&(v->cols[i - 1].nds));
if(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
return TRUE;
if(v->cols[i - 1].data_size < v->cols[i - 1].nds)
luaodbc_coldata_realloc(v, i - 1, v->cols[i - 1].nds + 1);
else
return FALSE;
}
return false;
} void *luastmt_dataptr(stmtType *v, int i)
{
if(i <= 0)
return false;
return v->cols[i - 1].data;
} BOOL luastmt_next(stmtType *v)
{
if(!(v->status & LOS_STMTOPENED))
return false;
v->gci = 0;
SQLRETURN rc = SQLFetch(v->hstmt);
return (rc != SQL_NO_DATA_FOUND);
} const char *luastmt_getstr(stmtType *v, int i)
{
if(!luastmt_get(v, i, SQL_C_CHAR))
return "";
return v->cols[i - 1].data;
} int luastmt_getint(stmtType *v, int i)
{
if(!luastmt_get(v, i, SQL_C_SLONG))
return -1;
return *(int*)(v->cols[i - 1].data);
} int _colindexfromename(stmtType *v, const char *name)
{
std::string str = name;
std::transform(str.begin(), str.end(), str.begin(), tolower);
for(short i = 0; i < v->col_count; i++)
{
if(str == (v->cols)[i].name)
return i + 1;
}
return -1;
} const char *luastmt_getstr_fn(stmtType *v, const char *name)
{
if(!name)
return "";
return luastmt_getstr(v, _colindexfromename(v, name));
} int luastmt_getint_fn(stmtType *v, const char *name)
{
if(!name)
return -1;
return luastmt_getint(v, _colindexfromename(v, name));
} BOOL luastmt_setstr(stmtType *v, int i, const char *str)
{
if(i <= 0 || !str)
return FALSE;
return luastmt_set(v, i, SQL_C_CHAR, (char*)str, strlen(str) + 1);
} BOOL luastmt_setint(stmtType *v, int i, int num)
{
if(!v || i <= 0)
return FALSE;
return luastmt_set(v, i, SQL_C_SLONG, (char*)&num, sizeof(int));
} BOOL luastmt_setstr_fn(stmtType *v, const char *name, const char *str)
{
if(!v || !name)
return false;
return luastmt_setstr(v, _colindexfromename(v, name), str);
} BOOL luastmt_setint_fn(stmtType *v, const char *name, int num)
{
if(!name)
return false;
return luastmt_setint(v, _colindexfromename(v, name), num);
} void luastmt_class_init(stmtType *v)
{
BYTE *psc = v->class_memory;
#define make_luastmt_shellcode(_member_, _sc_t_, _pup_, _proc_) *(DWORD*)&(v->thisobj._member_) = (DWORD)psc; \
memcpy_s(psc, sizeof(_sc_t_), _sc_t_, sizeof(_sc_t_)); \
*(DWORD*)(psc + _pup_) = (DWORD)v; \
*(DWORD*)(psc + _pup_ + 5) = (DWORD)_proc_ - (DWORD)(psc + _pup_ + 5 - 1) - 5; \
psc += sizeof(_sc_t_)
make_luastmt_shellcode(close, scT1, SCTP1, luastmt_close);
make_luastmt_shellcode(set, scT5, SCTP5, luastmt_set);
make_luastmt_shellcode(get, scT3, SCTP3, luastmt_get);
make_luastmt_shellcode(data, scT1, SCTP1, luastmt_dataptr);
make_luastmt_shellcode(next, scT1, SCTP1, luastmt_next);
make_luastmt_shellcode(getstr, scT2, SCTP2, luastmt_getstr);
make_luastmt_shellcode(getint, scT2, SCTP2, luastmt_getint);
make_luastmt_shellcode(getstr_fn, scT2, SCTP2, luastmt_getstr_fn);
make_luastmt_shellcode(getint_fn, scT2, SCTP2, luastmt_getint_fn);
make_luastmt_shellcode(setstr, scT3, SCTP3, luastmt_setstr);
make_luastmt_shellcode(setint, scT3, SCTP3, luastmt_setint);
make_luastmt_shellcode(setstr_fn, scT3, SCTP3, luastmt_setstr_fn);
make_luastmt_shellcode(setint_fn, scT3, SCTP3, luastmt_setint_fn);
} void luastmt_colinfo_release(stmtType *v)
{
for(int i = 0; i < v->cp_size; i++)
{
if(v->cols[i].data)
{
delete v->cols[i].data;
v->cols[i].data = NULL;
}
}
delete v->cols;
} void luastmt_colinfo_init(stmtType *v)
{
short count;
SQLNumResultCols(v->hstmt, &count);
if(count > v->cp_size)
{
luastmt_colinfo_release(v);
v->cp_size = count;
v->cols = new ciType[count];
memset(v->cols, 0, sizeof(ciType) * count);
}
v->col_count = count;
char szColName[68];
SQLSMALLINT cbColName, sqlColType, ibScale, fNullable;
SQLUINTEGER cbColDef;
for(short i = 0; i < count; i++)
{
SQLDescribeColA(v->hstmt, i + 1, (SQLCHAR*)szColName, 68, &cbColName, &sqlColType, &cbColDef, &ibScale, &fNullable);
for(short j = 0; j < cbColName; j++)szColName[j] = tolower(szColName[j]);
memcpy_s(v->cols[i].name, 68, szColName, cbColName + 1);
if(v->cols[i].data_size < (int)cbColDef + 1)
{
if(v->cols[i].data)
delete v->cols[i].data;
v->cols[i].data_size = cbColDef + 1;
v->cols[i].data = new char[cbColDef + 1];
}
v->cols[i].type = sqlColType;
v->cols[i].type_len = cbColDef;
}
} void luastmt_release(stmtType *v)
{
luastmt_colinfo_release(v);
VirtualFree(v->class_memory, 0, MEM_RELEASE);
delete v;
} stmtType *luaodbc_newstmt(_odbcType *parent)
{
stmtType *v = new stmtType;
memset(v, 0, sizeof(stmtType));
v->cp_size = 64;
v->cols = new ciType[64];
memset(v->cols, 0, sizeof(ciType) * 64);
v->status = LOS_CLOSED;
v->next = NULL;
v->parent = parent;
v->class_memory = (unsigned char *)VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
luastmt_class_init(v);
return v;
} void luaodbc_tran_begin(odbcType *v)
{
SQLSetConnectAttrA(v->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_FALSE, NULL);
v->status |= LOS_TRAN;
} void luaodbc_tran_end(odbcType *v, int ct)
{
SQLEndTran(SQL_HANDLE_DBC, v->hdbc, (short)ct);
SQLSetConnectAttrA(v->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_TRUE, NULL);
v->status ^= LOS_TRAN;
} void luaodbc_close(odbcType *v)
{
if(v->status & LOS_CONNECTIONED)
{
stmtType *s = v->stmt_list;
do{
luastmt_close(s);
s = s->next;
}while(s);
if(v->status & LOS_TRAN)
luaodbc_tran_end(v, SQL_ROLLBACK);
SQLDisconnect(v->hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, v->hdbc);
v->status ^= LOS_CONNECTIONED;
v->hdbc = NULL;
}
} BOOL luaodbc_open(odbcType *v, const char *dsn)
{
luaodbc_close(v);
SQLHANDLE hdbc;
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_DBC, v->henv, &hdbc);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return FALSE;
rc = SQLConnectA(hdbc, (SQLCHAR*)dsn, SQL_NTS, NULL, 0, NULL, 0);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
return FALSE;
}
v->hdbc = hdbc;
v->status |= LOS_CONNECTIONED;
return TRUE;
} luastmt_class *luaodbc_exec(odbcType *v, const char *sql)
{
stmtType *s = v->stmt_list;
stmtType *b = s;
do{
if(!(s->status & LOS_STMTOPENED))
break;
b = s;
s = s->next;
}while(s); if(!s)
{
s = luaodbc_newstmt(v);
b->next = s;
} SQLHANDLE hstmt;
SQLRETURN rc;
if(!(v->status & LOS_CONNECTIONED))
return NULL; rc = SQLAllocHandle(SQL_HANDLE_STMT, v->hdbc, &hstmt);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return FALSE;
SQLCancel(hstmt);
#if(_MSC_VER < 1300)
SQLSetStmtOption(hStmt, SQL_CONCURRENCY, SQL_CONCUR_VALUES);
SQLSetStmtOption(hStmt, SQL_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
#else
SQLSetStmtAttr(hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_VALUES, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);
#endif
rc = SQLExecDirectA(hstmt, (SQLCHAR*)sql, SQL_NTS);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
//printf("ERROR:[ODBC::Connection::Execute]->%s\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
return FALSE;
}
s->hstmt = hstmt;
luastmt_colinfo_init(s);
s->status |= LOS_STMTOPENED;
return &(s->thisobj);
} void luaodbc_class_init(odbcType *v)
{
BYTE *psc = v->class_memory;
#define make_luaodbc_shellcode(_member_, _sc_t_, _pup_, _proc_) *(DWORD*)&(v->thisobj._member_) = (DWORD)psc; \
memcpy_s(psc, sizeof(_sc_t_), _sc_t_, sizeof(_sc_t_)); \
*(DWORD*)(psc + _pup_) = (DWORD)v; \
*(DWORD*)(psc + _pup_ + 5) = (DWORD)_proc_ - (DWORD)(psc + _pup_ + 5 - 1) - 5; \
psc += sizeof(_sc_t_)
make_luaodbc_shellcode(open, scT2, SCTP2, luaodbc_open);
make_luaodbc_shellcode(close, scT1, SCTP1, luaodbc_close);
make_luaodbc_shellcode(exec, scT2, SCTP2, luaodbc_exec);
make_luaodbc_shellcode(tran_begin, scT1, SCTP1, luaodbc_tran_begin);
make_luaodbc_shellcode(tran_end, scT2, SCTP2, luaodbc_tran_end);
} __declspec(dllexport) luadbc_class *luadbc_init()
{
odbcType *v = new odbcType;
memset(v, 0, sizeof(odbcType));
SQLRETURN rc;
rc = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &(v->henv));
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
return NULL;
rc = SQLSetEnvAttr(v->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
{
SQLFreeHandle(SQL_HANDLE_ENV, v->henv);
v->henv = NULL;
return NULL;
}
v->stmt_list = luaodbc_newstmt(v);
v->status = LOS_INITILZED;
v->class_memory = (unsigned char *)VirtualAlloc(NULL, 512, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
luaodbc_class_init(v);
v->thisobj.dbc_obj = v;
EnterCriticalSection(&g_safe_luaodbc_cs);
g_safe_luaodbc_list.push_back((int)&(v->thisobj));
LeaveCriticalSection(&g_safe_luaodbc_cs);
return (luadbc_class*)&(v->thisobj);
} __declspec(dllexport) void luadbc_exit(luadbc_class *obj)
{
EnterCriticalSection(&g_safe_luaodbc_cs);
auto it = std::find(g_safe_luaodbc_list.begin(), g_safe_luaodbc_list.end(), (int)obj);
if(it == g_safe_luaodbc_list.end())
{
LeaveCriticalSection(&g_safe_luaodbc_cs);
return;
}
g_safe_luaodbc_list.erase(it);
LeaveCriticalSection(&g_safe_luaodbc_cs);
odbcType *v = (odbcType*)(((luadbc_class_ex*)obj)->dbc_obj);
VirtualFree(v->class_memory, 0, MEM_RELEASE);
luaodbc_close(v);
stmtType *s = v->stmt_list;
stmtType *b;
do{
b = s;
s = s->next;
luastmt_release(b);
}while(s);
SQLFreeHandle(SQL_HANDLE_ENV, v->henv);
delete v;
}
}
--luajit中这样调用
local ffi = require("ffi")
ffi.cdef[[
typedef struct{
void (*close)();
bool (*set)(int i, int type, char *data, int size);
bool (*get)(int i, int type);
void *(*data)();
bool (*next)();
char *(*getstr)(int i);
int (*getint)(int i);
char *(*getstr_fn)(const char *name);
char *(*getint_fn)(const char *name);
bool (*setstr)(int i, const char *str);
bool (*setint)(int i, int num);
bool (*setstr_fn)(const char *name, const char *str);
bool (*setint_fn)(const char *name, int num);
}luastmt_class; typedef struct{
bool (*open)(const char*dsn);
void (*close)();
luastmt_class *(*exec)(const char *sql);
void (*tran_begin)();
void (*tran_end)(int ct);
}luadbc_class; luadbc_class *luadbc_init();
void luadbc_exit(luadbc_class *obj);
]] local conn = ffi.C.luadbc_init(); if conn.open("USERDSN") ~= false then
print("已连接!")
local rs = conn.exec("SELECT * FROM characters")
if rs ~= nil then
print("開始遍历数据!")
while rs.next() do
print(ffi.string(rs.getstr(3)))
end
rs.close()
end
conn.close()
end

luajit利用ffi结合C语言实现面向对象的封装库的更多相关文章

  1. 用C语言实现面向对象的开发

    C语言的对象化模型 面向对象的特征主要包括: .封装,隐藏内部实现 .继承,复用现有代码 .多态,改写对象行为 采用C语言实现的关键是如何运用C语言本身的特性来实现上述面向对象的特征. 1.1 封装 ...

  2. 基于C语言的面向对象编程

    嵌入式软件开发中,虽然很多的开发工具已经支持C++的开发,但是因为有时考虑运行效率和编程习惯,还是有很多人喜欢用C来开发嵌入式软件.Miro Samek说:"我在开发现场发现,很多嵌入式软件 ...

  3. 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\

    1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...

  4. LuaJIT 之 FFI

    1. FFI 教程 原文: FFI Tutorial 相关链接:OpenResty 最佳实践之 FFI 加载 FFI 库 FFI 库时默认编译进 LuaJIT 中的,但是不会默认加载或初始化.因此,当 ...

  5. 使C语言实现面向对象的三个要素,你掌握了吗?

  6. Python语言之面向对象

    Python语言之面向对象 前言 面向对象 -- Object Oriented 简写:OO 面向对象设计 -- Object Oriented Design 简写:OOD 面向对象编程 -- Obj ...

  7. Objective-C语言的面向对象特性

    Objective-C作为一种面向对象的编程语言,具有面向对象的基本特征,即:封装.继承和多态.主要介绍Objective-C中有关面向对象基本概念:类.对象.方法和属性等. 类是Objective- ...

  8. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  9. 第二十五节:Java语言基础-面向对象基础

    面向对象 面向过程的代表主要是C语言,面向对象是相对面向过程而言,Java是面向对象的编程语言,面向过程是通过函数体现,面向过程主要是功能行为. 而对于面向对象而言,将功能封装到对象,所以面向对象是基 ...

随机推荐

  1. Perl语言入门:第六章习题:处理用户所指定的名字并汇报相应的姓。

    37 print "\n----------------------------------_exercise_6_1--------------------------\n";  ...

  2. 梯度提升决策树(GBDT)与XGBoost、LightGBM

    今天是周末,之前给自己定了一个小目标:每周都要写一篇博客,不管是关于什么内容的都行,关键在于总结和思考,今天我选的主题是梯度提升树的一些方法,主要从这些方法的原理以及实现过程入手讲解这个问题. 本文按 ...

  3. Linux基础学习二

    新建分区:fdisk /dev/sda(a代表第一块硬盘)                   建完后w保存 更新分区表:partprobe mkfs.ext4 /dev/sdb{1..3} : 格式 ...

  4. [Python3网络爬虫开发实战] 1.2.3-ChromeDriver的安装

    前面我们成功安装好了Selenium库,但是它是一个自动化测试工具,需要浏览器来配合使用,本节中我们就介绍一下Chrome浏览器及ChromeDriver驱动的配置. 首先,下载Chrome浏览器,方 ...

  5. jq ajax请求error: Maximum call stack size exceeded

    原因是data中参数iconUrl这个变量未声明导致的.jq在内部循环时报错

  6. 基于PHP的微信支付教程

    微信支付作为各大移动支付方式之一,本课程只要向大家介绍并使用微信支付的常用功能,进而集合到已有的项目中去,希望各位能够快速上手并掌握实战"干货". 出处至:汇智网  hubwiz. ...

  7. 简述FTP主动模式与被动模式

    1 FTP工作模式 2 不同模式FTP面临的问题 3 主动模式的FTP连接建立连接主要步骤 客户端打开一个随机的端口(端口号大于1024,在这里,我们称它为x),同时一个FTP进程连接至服务器的21号 ...

  8. Centos下PHP7.1打开Oracle扩展

    背景 最近因为项目研究了一下PHP集成Oracle,虽然这个组合很奇葩,但万一用到请勿采坑~ 环境 CentOS Linux release 7.3.1611 (Core) PHP7.1.1 安装or ...

  9. linux目录文件操作

    一.linux系统目录结构 1.顶层根目录 顶层根目录使用 “/”来表示 2.linux中的一些重要目录 (1)bin目录 放置常用的可执行文件(其中ls命令位列其中) (2)sbin目录 放置系统的 ...

  10. 7-9 旅游规划(25 分)(Dijkstra最短路径算法)

    有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径.如果有若干条路径都是最短的,那么需要输出最便 ...