最近阅读了Redis6.2源码,添加了一些注释,感兴趣的同学可以看下。
https://github.com/neohope/NeoRedisSrc
Category Archives: C
编译Wkhtmltopdf
1、首先下载源码
git clone https://github.com/wkhtmltopdf/wkhtmltopdf.git D:\GitHub\wkhtmltopdf git clone https://github.com/wkhtmltopdf/qt.git D:\GitHub\wkhtmltopdf\qt
2、安装下面几个软件
VS2013
Python2.7
ActivePerl
NSIS
3、初始化环境变量
set GIT_HOME=C:\Program Files\Git set NSIS_HOME=C:\NeoLanguages\NSIS set PYTHON_HOME=C:\NeoLanguages\Python27_x86 set PERL_HOME=C:\NeoLanguages\Perl set PATH=%GIT_HOME%\bin;%PYTHON_HOME%;%PERL_HOME%\bin;%NSIS_HOME%;%PATH% @call C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat x86
4、编译
python scripts\build.py msvc2013-win32
PS:
如果编译失败,一般是由于依赖包的网站无法方位导致的,你懂的。
这个时候,打开build.py文件,找到DEPENDENT_LIBS,自备梯子,下载后直接放到static-build路径下就好了。
posix_memalign函数在Windows下的实现
posix_memalign函数主要用于申请内存时,做内存对齐使用,Windows下对应的函数为_aligned_malloc,但两者的参数有一定区别:
int posix_memalign(void **memptr, size_t alignment, size_t size); void * _aligned_malloc(size_t size, size_t alignment);
从stackoverflow上,找到了两种实现方式,对于第一种,我只能说,佩服佩服。
1、最简练的实现方式
#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
2、比较稳妥的实现方式
#ifdef _WIN32
static int check_align(size_t align)
{
for (size_t i = sizeof(void *); i != 0; i *= 2)
if (align == i)
return 0;
return EINVAL;
}
int posix_memalign(void **ptr, size_t align, size_t size)
{
if (check_align(align))
return EINVAL;
int saved_errno = errno;
void *p = _aligned_malloc(size, align);
if (p == NULL)
{
errno = saved_errno;
return ENOMEM;
}
*ptr = p;
return 0;
}
#endif
DBUS发送接收数据(下)
1、编译后,由于没有进行配置,默认是无法运行的。
为了可以正常运行,增加或修改下面的配置文件即可。
/etc/dbus-1.0/system-local.conf
<!-- This configuration file controls the systemwide message bus.
Add a system-local.conf and edit that rather than changing this
file directly. -->
<!-- Note that there are any number of ways you can hose yourself
security-wise by screwing up this file; in particular, you
probably don't want to listen on any more addresses, add any more
auth mechanisms, run as a different user, etc. -->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Our well-known bus type, do not change this -->
<type>system</type>
<!-- Run as special user -->
<user>messagebus</user>
<!-- Fork into daemon mode -->
<fork/>
<!-- We use system service launching using a helper -->
<standard_system_servicedirs/>
<!-- This is a setuid helper that is used to launch system services -->
<servicehelper>/usr/lib/dbus-1.0/dbus-daemon-launch-helper</servicehelper>
<!-- Write a pid file -->
<pidfile>/var/run/dbus/pid</pidfile>
<!-- Enable logging to syslog -->
<syslog/>
<!-- Only allow socket-credentials-based authentication -->
<auth>EXTERNAL</auth>
<!-- Only listen on a local socket. (abstract=/path/to/socket
means use abstract namespace, don't really create filesystem
file; only Linux supports this. Use path=/whatever on other
systems.) -->
<listen>unix:path=/var/run/dbus/system_bus_socket</listen>
<policy context="default">
<!-- All users can connect to system bus -->
<allow user="*"/>
<!-- Holes must be punched in service configuration files for
name ownership and sending method calls -->
<allow own="*"/>
<allow send_type="method_call"/>
<!-- Signals and reply messages (method returns, errors) are allowed
by default -->
<allow send_type="signal"/>
<allow send_requested_reply="true" send_type="method_return"/>
<allow send_requested_reply="true" send_type="error"/>
<!-- All messages may be received by default -->
<allow receive_type="method_call"/>
<allow receive_type="method_return"/>
<allow receive_type="error"/>
<allow receive_type="signal"/>
<!-- Allow anyone to talk to the message bus -->
<allow send_destination="org.freedesktop.DBus"/>
<!-- But disallow some specific bus services -->
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus"
send_member="UpdateActivationEnvironment"/>
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.systemd1.Activator"/>
</policy>
<!-- Only systemd, which runs as root, may report activation failures. -->
<policy user="root">
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.systemd1.Activator"/>
</policy>
<!-- Config files are placed here that among other things, punch
holes in the above policy for specific services. -->
<includedir>system.d</includedir>
<include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
</busconfig>
2、测试消息发送
服务端:
$./testdbus_s.bin receive Listening for signals Match rule sent Got Signal with value: Hello Got Signal with value: Hi Bye......
客户端:
$./testdbus_s.bin send Hello Sending signal with value: Hello Signal Sent $./testdbus_s.bin send Hi Sending signal with value: Hi Signal Sent $./testdbus_s.bin send Bye Sending signal with value: Bye Signal Sent
3、测试方法调用
服务端:
$./testdbus_s.bin listen Listening for method calls Method Invoked with value: Hello Method Invoked with value: Hi Bye......
客户端:
$./testdbus_s.bin query Hello Calling remote method with Hello Request Sent Got Reply: 1, 21614 $./testdbus_s.bin query Hi Calling remote method with Hi Request Sent Got Reply: 1, 21614 $./testdbus_s.bin query Bye Calling remote method with Bye Request Sent Got Reply: 1, 21614
DBUS发送接收数据(上)
1、Server端
testdbus_s.c
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
/**
* Wait for signals on the bus and reply
*/
void receive()
{
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
int ret;
char* sigvalue;
int loop=1;
printf("Listening for signals\n");
// initialise the errors
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}
// request our name on the bus and check for errors
ret = dbus_bus_request_name(conn, "neohope.dbus.signal.target", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
exit(1);
}
// add a rule for which messages we want to see
dbus_bus_add_match(conn, "type='signal',interface='neohope.dbus.signal.Type'", &err); // see signals from the given interface
dbus_connection_flush(conn);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
printf("Match rule sent\n");
// loop listening for signals being emmitted
while (loop) {
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't read a message
if (NULL == msg) {
sleep(1);
continue;
}
// check if the message is a signal from the correct interface and with the correct name
if (dbus_message_is_signal(msg, "neohope.dbus.signal.Type", "TestSignal")) {
// read the parameters
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "Message Has No Parameters\n");
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not string!\n");
else
dbus_message_iter_get_basic(&args, &sigvalue);
if(strcmp("Bye",sigvalue)==0) {
loop = 0;
printf("Bye......\n");
}
else {
printf("Got Signal with value: %s\n", sigvalue);
}
}
// free the message
dbus_message_unref(msg);
}
// do not close the connection
// dbus_connection_close(conn);
}
/**
* Deal with remote method call
*/
int reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
{
DBusMessage* reply;
DBusMessageIter args;
int stat = 1;
int ret = 1;
dbus_uint32_t level = 21614;
dbus_uint32_t serial = 0;
char* param = "";
// read the arguments
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "Message has no arguments!\n");
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not string!\n");
else
dbus_message_iter_get_basic(&args, ¶m);
if(strcmp("Bye",param)==0){
ret = 0;
printf ("Bye......\n");
}
else {
printf("Method Invoked with value: %s\n", sigvalue);
}
// create a reply from the message
reply = dbus_message_new_method_return(msg);
// add the arguments to the reply
dbus_message_iter_init_append(reply, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
// send the reply && flush the connection
if (!dbus_connection_send(conn, reply, &serial)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
dbus_connection_flush(conn);
// free the reply
dbus_message_unref(reply);
return ret;
}
/**
* Server that exposes a method call and waits for it to be called
*/
void listen()
{
DBusMessage* msg;
DBusMessage* reply;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
int loop = 1;
int ret;
char* param;
printf("Listening for method calls\n");
// initialise the error
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
fprintf(stderr, "Connection Null\n");
exit(1);
}
// request our name on the bus and check for errors
ret = dbus_bus_request_name(conn, "neohope.dbus.method.provider", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
fprintf(stderr, "Not Primary Owner (%d)\n", ret);
exit(1);
}
// loop, testing for new messages
while (loop) {
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't got a message
if (NULL == msg) {
sleep(1);
continue;
}
// check this is a method call for the right interface & method
if (dbus_message_is_method_call(msg, "neohope.dbus.method.Type", "TestMethod"))
loop = reply_to_method_call(msg, conn);
// free the message
dbus_message_unref(msg);
}
// do not close the connection
// dbus_connection_close(conn);
}
int main(int argc, char** argv)
{
if (2 > argc) {
printf ("Syntax: testdbus_s [receive|listen] [<param>]\n");
return 1;
}
char* param = "no param";
if (3 >= argc && NULL != argv[2]) param = argv[2];
if (0 == strcmp(argv[1], "receive"))
receive();
else if (0 == strcmp(argv[1], "listen"))
listen();
else {
printf ("Syntax: testdbus_s [receive|listen] [<param>]\n");
return 1;
}
return 0;
}
2、Client端
testdbus_c.c
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
/**
* Connect to the DBUS bus and send a broadcast signal
*/
void sendsignal(char* sigvalue)
{
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
int ret;
dbus_uint32_t serial = 0;
printf("Sending signal with value: %s\n", sigvalue);
// initialise the error value
dbus_error_init(&err);
// connect to the DBUS system bus, and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}
// register our name on the bus, and check for errors
ret = dbus_bus_request_name(conn, "neohope.dbus.signal.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
exit(1);
}
// create a signal & check for errors
msg = dbus_message_new_signal("/neohope/dbus/signal/Object", // object name of the signal
"neohope.dbus.signal.Type", // interface name of the signal
"TestSignal"); // name of the signal
if (NULL == msg)
{
fprintf(stderr, "Message Null\n");
exit(1);
}
// append arguments onto signal
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
// send the message and flush the connection
if (!dbus_connection_send(conn, msg, &serial)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
dbus_connection_flush(conn);
printf("Signal Sent\n");
// free the message
dbus_message_unref(msg);
// do not close the connection
// dbus_connection_close(conn);
}
/**
* Call a method on a remote object
*/
void query(char* param)
{
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
DBusPendingCall* pending;
int ret;
int stat;
dbus_uint32_t level;
printf("Calling remote method with %s\n", param);
// initialiset the errors
dbus_error_init(&err);
// connect to the system bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}
// request our name on the bus
ret = dbus_bus_request_name(conn, "neohope.dbus.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
exit(1);
}
// create a new method call and check for errors
msg = dbus_message_new_method_call("neohope.dbus.method.provider", // target for the method call
"/neohope/dbus/method/Object", // object to call on
"neohope.dbus.method.Type", // interface to call on
"TestMethod"); // method name
if (NULL == msg) {
fprintf(stderr, "Message Null\n");
exit(1);
}
// append arguments
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
// send message and get a handle for a reply
if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
if (NULL == pending) {
fprintf(stderr, "Pending Call Null\n");
exit(1);
}
dbus_connection_flush(conn);
printf("Request Sent\n");
// free message
dbus_message_unref(msg);
// block until we recieve a reply
dbus_pending_call_block(pending);
// get the reply message
msg = dbus_pending_call_steal_reply(pending);
if (NULL == msg) {
fprintf(stderr, "Reply Null\n");
exit(1);
}
// free the pending message handle
dbus_pending_call_unref(pending);
// read the parameters
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "Message has no arguments!\n");
else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not boolean!\n");
else
dbus_message_iter_get_basic(&args, &stat);
if (!dbus_message_iter_next(&args))
fprintf(stderr, "Message has too few arguments!\n");
else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not int!\n");
else
dbus_message_iter_get_basic(&args, &level);
printf("Got Reply: %d, %d\n", stat, level);
// free reply and close connection
dbus_message_unref(msg);
//dbus_connection_close(conn);
}
int main(int argc, char** argv)
{
if (2 > argc) {
printf ("Syntax: testdbus_c [send|query] [<param>]\n");
return 1;
}
char* param = "no param";
if (3 >= argc && NULL != argv[2]) param = argv[2];
if (0 == strcmp(argv[1], "send"))
sendsignal(param);
else if (0 == strcmp(argv[1], "query"))
query(param);
else {
printf ("Syntax: testdbus_c [send|query] [<param>]\n");
return 1;
}
return 0;
}
3、Makefile
CC=gcc LDFLAGS+=-ldbus-1 CFLAGS+=-I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include/ all:testdbus_c.bin testdbus_s.bin testdbus_c.bin:testdbus_c.o $(CC) $(LDFLAGS) -o testdbus_c.bin testdbus_c.o testdbus_c.o:testdbus_c.c $(CC) $(CFLAGS) -c -o testdbus_c.o testdbus_c.c testdbus_s.bin:testdbus_s.o $(CC) $(LDFLAGS) -o testdbus_s.bin testdbus_s.o testdbus_s.o:testdbus_s.c $(CC) $(CFLAGS) -c -o testdbus_s.o testdbus_s.c clean: rm *.o *.bin
4、编译
make
用VC编译Nginx
1、安装Mysis和VC
2、用svn从Nginx取回源代码
3、调用下面的bat
@call "D:\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" @call "D:\GNUstep\msys.bat" cmd
4、Config
./auto/configure --prefix= --sbin-path=nginx --with-cc=cl --with-cc-opt="" --without-http_rewrite_module --without-http_gzip_module
5、Make
nmake
函数调用约定
1.STDCALL
微软制定的c语言调用约定,也就是传说中的WINAPI
参数从右向左进行压栈(微软官方文档说从左向右压栈),返回值存在eax中,
被调用函数清理栈,不允许变长参数列表
函数名前增加_,函数名后增加@和参数个数(32位机器上一定被4整除)
ret指令中,有可选参数指定有多少字节需要弹栈
2.CDECL
c语言的默认调用约定
参数从右向左进行压栈,返回值存在eax中,
调用函数清理栈,可用变长参数列表
函数名前会增加_
3.FASTCALL
非跨编译器的c语言调用约定,
前2-3个4字节内的参数被存放到寄存器(edx,eax,ecx)中,其他参数,或大于4字节的参数,按从右到左的顺序被存放在栈中
多数情况下,调用函数负责清理栈
仅适用于参数少,而且实时性要求很高的情况下
函数名前增加@,函数名后增加@和参数个数
4.THISCALL
cpp的调用约定
参数从右向左进行压栈,返回值存在eax中,this指针存在ecx中
每种编译器对函数名称有不同的修饰方法,但基于重载的需要,一般都会增加参数类型和类名
当使用extern “C”的时候,cpp编译器会使用c语言的修饰方法来修饰函数名,这样就可以方便的供别人调用了。
c与cpp输出16进制,8进制及ASCII
1.c
#include <stdio.h>
int main(int argc,char **argv)
{
for(int i=0;i<=127;i++)
{
printf("%X-%03o-%c\n",i,i,i);
}
return 0;
}
2.cpp
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc,char **argv)
{
for(int i=0;i<=127;i++)
{
cout<<setw(2)<<setfill('0')<<hex<<i<<"-"<<setw(3)<<setfill('0')<<oct<<i<<"-"<<dec<<(char)i<<endl;
}
return 0;
}
c语言中,用函数实现sizeof操作
大家都知道,c语言中sizeof是个操作符,在编译阶段已经变成了数值
要用函数实现sizeof的话,和sizeof操作符是会有一定区别的
这里,我只给出了一个很简单的例子,
用指针操作实现sizeof(double)的功能
double a=0.0; int sz=(int)&((&a)[1])-(int)&a;
小红伞与gcc
昨天试着用MinGW编译FFMPEG,网上资料是很多,但我遇到了一个很让人郁闷的问题:
只要一./configure …
就显示gcc测试失败
纠结了一整天,最后发现居然是小红伞把测试gcc时生成的exe当成病毒处理掉了,晕
关闭小红伞,一切太平了
希望大家不要遇到这种问题
测试用例:
源码a.c
int main(){return 0;}
编译
gcc -o a.exe a.c
小红伞会报a.exe为病毒