是的,这个问题已被多次询问,我一直在寻找和阅读论坛,以及SO帖子,但答案都与这个问题无关(或者看起来似乎)。所以,我有这个主文件:
- sgbd_server.c -
#include "sgbd_server.h"
/**
* Open server pipe and return handle. -1 = error
*/
int open_server_pipe() {
return pipe_open(FIFO_NAME, O_RDONLY, S_CON_COLOR);
}
/**
* Close server pipe
*/
void close_server_pipe(int fd) {
pipe_close(fd, FIFO_NAME, S_CON_COLOR);
}
int main(int argc, char *argv[]) {
int pipe_fd;
pipe_fd = open_server_pipe();
if (pipe_fd == -1) {
perror("Cannot open pipe");
}
close_server_pipe(pipe_fd);
exit(EXIT_SUCCESS);
}
然后是头文件:
- sgbd_server.h -
#include "common.h"
#define FIFO_NAME "./sgbd_server_pipe"
#define BUFFER_SIZE PIPE_BUF
#define S_CON_COLOR 1 /* C_COLOR_RED */
- common.h -
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "console.h"
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
int pipe_open(char *f, int mode, int color);
void pipe_close(int pipe_fd, char *f, int color);
pipe_open
和pipe_close
这两个函数在pipe.c
中定义,基本上返回0
和void
。最后一个文件在Make文件中单独编译。
我不是制作文件的大师,但为了这个问题,这里是:
SERVER = sgbd_server
CLIENT = sgbd_client
CC = gcc
C_FLAGS = -Wall -I.
LINKER = gcc
L_FLAGS = -Wall -l pthread -Wall -I.
RM = rm -f
client: sgbd_client.o pipe.o console.o
@echo -n "Building client... "
@$(LINKER) $(L_FLAGS) -o $(CLIENT) sgbd_client.o pipe.o console.o
@echo "Complete!\n"
server: sgbd_server.o pipe.o console.o
@echo -n "Building server... "
@$(LINKER) $(L_FLAGS) -o $(SERVER) sgbd_server.o pipe.o console.o
@echo "Complete!\n"
sgbd_client.o: sgbd_client.c
@echo -n "Refreshing client sources... "
@$(CC) $(C_FLAGS) -c sgbd_client.c
@echo "Done!"
sgbd_server.o: sgbd_server.c common.h
@echo -n "Refreshing server sources..."
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
@echo "Done!"
pipe.o: pipe.c
@echo -n "Refreshing pipe sources..."
@$(CC) $(C_FLAGS) -c pipe.c
@echo "Done!"
console.o: console.c
@echo -n "Refreshing console sources..."
@$(CC) $(C_FLAGS) -c console.c
@echo "Done!"
clean:
@echo -n "Cleaning up executables and object files... "
@$(RM) $(SERVER) $(CLIENT) *.o
@echo "Ok\n"
** 注意 **:文件console.c
并实现一些控制控制台I / O的功能,没什么特别的。如您所见,它也是单独编译的。
现在,当我输入make client
时,一切都很好,鸟类正在签名等等。但是当我输入make server
时,它会吐出来
sgbd_server.c: In function ‘open_server_pipe’:
sgbd_server.c:7: warning: implicit declaration of function ‘pipe_open’
sgbd_server.c: In function ‘close_server_pipe’:
sgbd_server.c:14: warning: implicit declaration of function ‘pipe_close’
我在Linux amd64上运行GCC,如果它有任何区别(我对此表示怀疑)。
现在,为什么要警告我呢?这两个函数在common.h
中声明,它包含在sgbd_server.h
中......我在这里缺少什么?
感谢您的时间!
** 更新 **
感谢大家的建议。我确实试图找到在我的包含路径中的某个地方是否会有一个文件common.h
以某种方式包含...但我找不到任何会在编译过程中滑落而不是本地{{} 1}}( sig )我在源文件夹中找到了一些common.h
个文件。由于.ghc
未清除它们,因此我手动删除了这些文件。你猜怎么着?没有警告。这些文件是什么?为什么要创建它们?
答案 0 :(得分:4)
首先,我不认为将common.h
提供给makefile中的编译器是个好主意:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
这样会更好:
@$(CC) $(C_FLAGS) -c sgbd_server.c
标题文件通常只包含#include
。您似乎在告诉编译器尝试将common.h
编译为独立的C文件。这是客户端和服务器编译命令之间的一个区别,你应该修复它。
我可以建议的唯一另一件事是你可能没有得到你认为你得到的头文件。首先来一行:
#error Urk! in common.h
位于common.h
的顶部,并确保构建失败。
如果没有,则该文件来自其他地方。您可能还希望对sgbd_server.h
文件执行相同的操作。
根据您的修改:
我发现一些.ghc文件位于我的源文件夹中。由于它们没有被make clean清理,我手动删除了这些文件。你猜怎么着?没有警告。这些文件是什么?为什么要创建它们?
这些是,假设ghc
是一个拼写错误,你的意思是gch
,由gcc
生成的预编译头文件,至少部分是为了加快编译过程。而不是必须在构建期间多次处理头文件(每个包含它的源文件一次),预编译一次并使用预编译版本效率更高。
我认为这很可能是因为您在执行服务器时在编译器命令行中包含了common.h
。默认情况下,直接提供给gcc
的头文件将转换为预编译的头文件,并在该点之后优先使用。为了测试这一点,我创建了一个qq.h
文件并执行gcc qq.h
并弹出qq.h.gch
。
很可能,因为删除它们解决了你的问题,这些文件以某种方式导致你的问题(是预先编译的标题比真实的标题或完全不同的东西存在)。您的编译行很有可能:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
首先编译服务器程序,包括旧的预编译头,然后从较新的头文件中生成一个新的预编译头。
这可能是common.h
的更改没有(立即)影响的原因。您必须make ; touch common.h ; make
以确保在服务器程序中使用了较新的预编译头文件。
你是否想追溯到根本原因并获得正确的解释是一个品味问题 - 有一种想法,你应该有时只记录你如何修复它而不是太担心,以免你被纠缠在现实本身的本质中。
当然不是我,我是那种试图将我的问题追溯到造成它的个别亚原子粒子的人格类型,但有时候实用主义需要我放手: - )
答案 1 :(得分:1)
观察:你在#define中有一个=我怀疑你并不想拥有那个
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
也许应该是
#define CLIENT_FIFO_PREFIX "./sgbd_client_"
评论:当原型包含正式参数名称(除了强制类型)并且函数的定义使用不同的形式参数名称时,我偶尔会目睹编译器的奇怪行为。即。在你的pipes.c。你管道 包括common.h?
此外,条件警卫#ifndef headerfilename #define headerfilename #endif 是一种很好的做法,但这与你的问题没有直接关系。
.PMCD。
答案 2 :(得分:0)
我怀疑你可能有另一个名为common.h的文件,而不是你期望的文件。我复制并粘贴了你的文件,编译后没有任何警告。
答案 3 :(得分:0)
您发布的文件中包含的内容看起来应该可以使用。一些想法还有什么可能是错的:
common.h
或console.h
是否会尝试包含sgbd_server.h
,以便您最终获得循环包含?#ifdef
)并可能将它们混合在某处,以便无意中排除其中一个文件?common.h
包含可能包含的路径而不是你想要的路径吗?