使 C 代码能够作为C++代码运行

Enabling C code to run as C++ code

本文关键字:代码 C++ 运行      更新时间:2023-10-16

我有一个C程序,可以在目录中查找重复的文件。该程序在命令行上执行并传递 2 个参数。一个是父目录,参数 2 是文件名。它是用 c 语言工作的代码,但我有一个 GUI 和其他用 c++ 编写的"微服务"文件。

如何从 c++ 文件中调用此 C 代码?

#include<stdio.h>
#include<dirent.h>
#include<sys/stat.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
//Compile:          gcc dreamduplicatefinder.c -o dreamduplicatefinder.exe
//Run:              ./dreamduplicateFinder.exe parent_dir filename...
#define false 0
#define true  1
int duplicateCount = 0;
int FindDuplicates(char* path, char* fileName);
int CompareFiles(char* originalFile, char* currFile);
int main(int argc, char *argv[])
{
    //Two additional arguments are expected: Parent dir, file to find duplicates of...
    if (argc != 3)
    {
        printf("Usage: %s 'Base Directory' 'File Name'n", argv[0]);
        return -1;
    }
    //argv[1] = base dir, argv[2] = file to find duplicates of; e.g argv[1] = /home,
    //argv[2] = "file.txt"...
    FindDuplicates(argv[1], argv[2]);
    printf("nnFound %d duplicate(s)n", duplicateCount);
    return 0;
}

int FindDuplicates(char* path, char* fileName)
{
    DIR *dir;
    struct dirent *dp;
    struct dirent *result;
    struct stat statp;
    char absoluteFilePath[255];
    if ((dir = opendir(path)) == NULL)
    {
        //printf(dir);                  //error could becuase trying to open shortcut or corrupt folder.
        printf("%sn",path);
        perror("Failed to open directory");
        return -1;
    }

    while ((dp = readdir(dir)) != NULL)
    {
        //readdir returns . and .. which we should ignore...
        if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, ".."))
        {
            //find file full path, relative to base path. e.g, a /home/file.txt...
            //copy path to absoluteFilePath...
            strcpy(absoluteFilePath, path);
            //append / at end...
            strcat(absoluteFilePath, "/");
            //append filename to path...
            strcat(absoluteFilePath, dp->d_name);

            //check if the current file is actually file or dir...
            stat(absoluteFilePath, &statp);
            if (S_ISDIR(statp.st_mode))     //is a directory...
            {
                //recurse through this dir...
                FindDuplicates(absoluteFilePath, fileName);
            }
            else if (S_ISREG(statp.st_mode))    //is a file...
            {
                //check for duplicates here...
                //compare current file with the file specified by user...
                if (strcmp(fileName, absoluteFilePath))
                {
                    if (CompareFiles(fileName, absoluteFilePath))
                    {
                        //yes, duplicate; print it...
                        printf("%sn", absoluteFilePath);
                        duplicateCount++;
                    }
                }
            }       //end else if (S_ISREG(statp.st_mode))...
        }       //if (strcmp(dp->d_name, ".") && strcmp(dp->d_name,".."))...
    }       //end while...
    closedir(dir);
    return 0;
}

int CompareFiles(char* originalFile, char* currFile)
{
    //two step comparison: (1) first check size; if not same, return false.
    //If equal, (2) compare file content.If equal, return true, false otherwise...
    struct stat statOriginal, statCurr;
    stat(originalFile, &statOriginal);
    stat(currFile, &statCurr);
    //Step 1...
    if ((int)statOriginal.st_size != (int)statCurr.st_size)  //size not same...
        return false;
    //Step 2...
    //size matches, files can be same; confirm it by matching both file contents...
    int fdOriginal = open(originalFile, O_RDONLY);
    int fdCurr = open(currFile, O_RDONLY);
    if (fdOriginal == -1 || fdCurr == -1)
        return false;       //error occurred, not sure if file is duplicate...

                            //we will read file in small chunks and compare...
    int chunkSize = 1024, bytesRead;
    char *bufferOriginal = (char*)malloc(chunkSize * sizeof(char));
    char *bufferCurr = (char*)malloc(chunkSize * sizeof(char));

    while (true)
    {
        //read file in chunk...
        bytesRead = read(fdOriginal, bufferOriginal, chunkSize);
        if (bytesRead <= 0)
            break;      //end of file...
        bytesRead = read(fdCurr, bufferCurr, bytesRead);
        //compare buffer...
        if (strcmp(bufferOriginal, bufferCurr))     //if content not matching...
            return false;
    }
    return true;
}

我的错误包括:(来自比较文件功能)

2x 未找到"打开"标识符

2x 未找到"读取"标识符

那些好奇的人的工作代码。谢谢@MarcusMüller@JesperJuhl

#include "stdafx.h"             //there is nothing in this header
#include<stdio.h>
#include<dirent.h>
#include<sys/stat.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
    //Compile:          gcc <name of this file>.cpp -o <nameOfThisFile>.exe
    //Run:              <nameOfThisFile> parent_dir filename...
#define false 0
#define true  1
    int duplicateCount = 0;
    int FindDuplicates(char* path, char* fileName);
    int CompareFiles(char* originalFile, char* currFile);
    int main(int argc, char *argv[])
    {
        //Two additional arguments are expected: Parent dir, file to find duplicates of...
        if (argc != 3)
        {
            printf("Usage: %s 'Base Directory' 'File Name'n", argv[0]);
            return -1;
        }
        //argv[1] = base dir, argv[2] = file to find duplicates of; e.g argv[1] = /home,
        //argv[2] = "file.txt"...
        FindDuplicates(argv[1], argv[2]);
        printf("nnFound %d duplicate(s)n", duplicateCount);
        return 0;
    }

    int FindDuplicates(char* path, char* fileName)
    {
        DIR *dir;
        struct dirent *dp;
        struct dirent *result;
        struct stat statp;
        char absoluteFilePath[255];
        if ((dir = opendir(path)) == NULL)
        {
            //possibly trying to open shortcut or corrupt folder typically.
            printf("Failed to open directory %s n",path);
            return -1;
        }

        while ((dp = readdir(dir)) != NULL)
        {
            //readdir returns . and .. which we should ignore...
            if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, ".."))
            {
                //find file full path, relative to base path. e.g, a /home/file.txt...
                //copy path to absoluteFilePath...
                strcpy(absoluteFilePath, path);
                //append / at end...
                strcat(absoluteFilePath, "/");
                //append filename to path...
                strcat(absoluteFilePath, dp->d_name);

                //check if the current file is actually file or dir...
                stat(absoluteFilePath, &statp);
                if (S_ISDIR(statp.st_mode))     //is a directory...
                {
                    //recurse through this dir...
                    FindDuplicates(absoluteFilePath, fileName);
                }
                else if (S_ISREG(statp.st_mode))    //is a file...
                {
                    //check for duplicates here...
                    //compare current file with the file specified by user...
                    if (strcmp(fileName, absoluteFilePath))
                    {
                        if (CompareFiles(fileName, absoluteFilePath))
                        {
                            //yes, duplicate; print it...
                            printf("This is a duplicate! %sn", absoluteFilePath);
                            duplicateCount++;
                        }
                    }
                }       //end else if (S_ISREG(statp.st_mode))...
            }       //if (strcmp(dp->d_name, ".") && strcmp(dp->d_name,".."))...
        }       //end while...
        closedir(dir);
        return 0;
    }

    int CompareFiles(char* originalFile, char* currFile)
    {
        //two step comparison: (1) first check size; if not same, return false.
        //If equal, (2) compare file content.If equal, return true, false otherwise...
        struct stat statOriginal, statCurr;
        stat(originalFile, &statOriginal);
        stat(currFile, &statCurr);
        //Step 1...
        if ((int)statOriginal.st_size != (int)statCurr.st_size)  //size not same...
            return false;
        FILE* fdOriginal;
        if (fdOriginal = fopen(originalFile, "r")) {
            if (fdOriginal == NULL) { fputs("File error", stderr); return false; }
        }
        else return false;        //error occurred, not sure if duplicate
        FILE* fdCurr;
        if (fdCurr = fopen(currFile, "r")) {
            if (fdCurr == NULL) { fputs("File error", stderr); return false; }
        }
        else return false;
        int chunkSize = 1024, objsRead;
        char *bufferOriginal = (char*)malloc(chunkSize * sizeof(char));
        if (bufferOriginal == NULL) { fputs("Memory error for buff orig", stderr); exit(2); }
        char *bufferCurr = (char*)malloc(chunkSize * sizeof(char));
        if (bufferCurr == NULL) { fputs("Memory error for buff curr", stderr); exit(2); }

        while (true)
        {
            //read file in chunk...
            //std::size_t fread( void* buffer, std::size_t size, std::size_t count, std::FILE* stream );
            objsRead = fread(bufferOriginal, sizeof(char), chunkSize , fdOriginal);
            if (objsRead <= 0)
                break;      //end of file...
            objsRead = fread(bufferCurr, sizeof(char), objsRead, fdCurr);
            //compare buffer...
            if (strcmp(bufferOriginal, bufferCurr))     //if content not matching...
                return false;
        }
        return true;
    }

你通常不会这样做。你可以把它包装在一个 C 函数中,然后编译成一个目标文件。

然后,您将在 extern "C" {…} 中包含 C 标头,并从 C++ 调用该函数。

构建可执行文件时,您将链接包含 C 函数的对象文件。做!

注意:C 不是C++,尽管你的代码在C++中不是非法的(据我立即判断),但它做了非常"丑陋"的事情(比如#define truefalse——呃,老实说,这在 C 中已经是一个坏主意了)。因此,处理它就像处理Fortran,Java或任何其他具有可以从C++使用的调用约定的语言(通常是C调用约定)一样:只需将其用作extern对象即可。

使用 ::open::read 应该可以找到函数。

您可能还希望将 C 标头(如"string.h")替换为其C++等效版本(如"cstring")。

你对truefalse的定义也应该去掉。在C++中,这些是真正的布尔值,而不是整数。这意味着CompareFiles的返回类型应更改为 bool

并且您应该将duplicateCount包装在一个匿名命名空间中 - 或者从更新它的函数中返回它(通过返回一个带有两个整数的小结构,或使用std::pairstd::tuple) - 全局变量是邪恶的。