C代码编译为C++,但不是C [重复]

Posted

技术标签:

【中文标题】C代码编译为C++,但不是C [重复]【英文标题】:C code compiles as C++, but not as C [duplicate] 【发布时间】:2010-06-29 17:11:17 【问题描述】:

可能重复:Convert some code from C++ to C

我有一些看起来是纯 C 的代码。当我告诉编译器(我使用 Visual Studio 2008 Express)将其编译为 c++ 时,它可以正常编译和链接。但是,当我尝试将其编译为 C 时,它会引发此错误:

1>InpoutTest.obj : error LNK2019: unresolved external symbol _Out32@8 referenced in function _main
1>InpoutTest.obj : error LNK2019: unresolved external symbol _Inp32@4 referenced in function _main

代码使用 Inpout.dll 读取和写入并行端口。我有 Inpout.lib 和 Inpout.dll。代码如下:

// InpoutTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
/* ----Prototypes of Inp and Outp--- */

short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);

/*--------------------------------*/

int main(int argc, char* argv[])


 int data;

 if(argc<3)
 
  //too few command line arguments, show usage
  printf("Error : too few arguments\n\n***** Usage *****\n\nInpoutTest read <ADDRESS> \nor \nInpoutTest write <ADDRESS> <DATA>\n\n\n\n\n");
  
 else if(!strcmp(argv[1],"read"))
 

  data = Inp32(atoi(argv[2]));

  printf("Data read from address %s is %d \n\n\n\n",argv[2],data);

 
 else if(!strcmp(argv[1],"write"))
 
  if(argc<4)
  
   printf("Error in arguments supplied");
   printf("\n***** Usage *****\n\nInpoutTest read <ADDRESS> \nor \nInpoutTest write <ADDRESS> <DATA>\n\n\n\n\n");
  
  else
  
  Out32(atoi(argv[2]),atoi(argv[3]));
  printf("data written to %s\n\n\n",argv[2]);
  
 



 return 0;

我之前问错了这个问题,here。

任何帮助将不胜感激。

【问题讨论】:

这些天 C 是否使用重命名?我正在查看链接器错误中的@4@8。看起来不像 C++ 名称修饰,除非我很困惑,但这些肯定不是未修饰的函数名称。 这只是对您上一个问题的小改写:***.com/questions/3142420/…。尽量不要重复发帖。 @Evan:我重新提问是因为我没有对另一个问题提出新的意见。对不起。 @Steve Visual Studio 将 _stdcall C 函数转换为 _name@number-of-bytes-passed-as-arguments; Inp32 有 4 个字节的参数,而 Out32 有 8 个。(reference) @Michael - 有道理,谢谢 【参考方案1】:

您正在尝试从 C 链接到 C++ 函数。由于名称修改,这不起作用 - 链接器不知道在哪里查找您的函数。如果要从 C++ 调用 C 函数,则必须将其标记为 extern "C"。据我所知,C 不支持外部“C++”。其他答案之一说有。或者,将其源代码重新编译为 C。

编辑:如果可以编译为 C++,为什么还要编译为 C?

【讨论】:

我需要从 C 项目中调用 Out32,如果我尝试编译为 C++,则会引发一堆错误。 我将 lib 的源代码重新编译为 C,它可以工作。 (在我将引用从 afxres.h 更改为 winres.h 之后)【参考方案2】:

听起来 Inp32Out32 是在 C++ 文件/库中外部定义的,因此您需要将它们标记为这样,以便编译器知道它们的名称将如何被破坏:

extern "C++" 
    short _stdcall Inp32(short PortAddress);
    void _stdcall Out32(short PortAddress, short data);

【讨论】:

这给出了错误 C2059: syntax error : 'string' extern "C++"吗?会不会是非便携的?我会在标明这些函数的头文件中使用extern "C",并使用#ifdef 保护,这样只有C++ 编译器才能看到它。 C 编译器已经使用 C 调用约定。 @Steve 有,尽管以另一种方式做更常见;我不确定可移植性,因为我实际上从未需要使用它。如果它是一个图书馆,他无法控制/拥有资源,因为他没有太多选择 extern C++ 是可移植的 C++,但在编译 C 翻译单元时不能使用(因为它不是 C),因此在这种特殊情况下不合适。 extern "C++" 很少有用 - 有一些 C++ 结构不能在 extern "C" 块内,但您通常不需要将它们放在那里。有关 extern "C++" 的使用示例,请参见 Microsoft 的 winnt.h。 @Michael - 如果他没有源代码,那么肯定要做的是编写一个小型适配器库吗?使用 C++ 编译的 C 链接函数调用提供的 C++ 函数。【参考方案3】:

如果您需要从 C 代码调用 C++ 例程,则 C++ 例程需要具有“C”链接,这是通过将函数标记为 extern "C" 来完成的。这需要在 C++ 端完成。

如果您能够更改现有的 C++ 代码,请将以下内容作为 Inp32()Outp32() 的原型。这应该在任何调用或定义 Inp32()Outp32() 函数的标头中 - 无论是 C 还是 C++ 代码:

#ifdef __cplusplus
extern "C" 
#endif

short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);

#ifdef __cplusplus

#endif

这会将这些函数标记为具有 C 调用约定,并且这些函数可由 C 或 C++ 代码调用。

如果您无法更改 C++ 代码,您可以在自己的 C++ 模块中为 C++ 函数创建自己的 C 兼容包装器:

wrappers.h 头文件:

// in wrappers.h

// C-callable wrappers

#ifndef WRAPPERS_H
#define WRAPPERS_H

#ifdef __cplusplus
extern "C" 
#endif

short Inp32_wrapper( short PortAddress);
void Out32_wrapper( short PortAddress, short data);    

#ifdef __cplusplus

#endif

#endif /* WRAPPERS_H */

还有,wrappers.cpp 实现:

// in wrappers.cpp file:

#include "wrappers.h"

// prototypes for the C++ functions - these really should be in a
//  header file...

short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);

// implementation of the wrappers

short Inp32_wrapper( short PortAddress)

    return Inp32( PortAddress);


void Out32_wrapper( short PortAddress, short data)

    Out32( PortAddress, data);

现在您的 C 代码可以#include "wrappers.h" 并调用包装函数,这些函数将简单地调用现有的 C++ 函数来完成工作。

【讨论】:

【参考方案4】:

这似乎不是编译器错误,而是链接器错误。链接器找不到Inp32Out32 的定义。您是否链接到包含定义的库?你拼写正确吗?

【讨论】:

我唯一做的就是更改文件的设置以编译为 C 而不是 C++。我没有改变任何链接或任何东西。我需要更改链接器设置吗?

以上是关于C代码编译为C++,但不是C [重复]的主要内容,如果未能解决你的问题,请参考以下文章

是否有编译为机器代码的 C C++ C# 编译器 [关闭]

如何将 c、c++ 和 python 代码编译为“Released/Final”版本? [关闭]

如何将javascript代码编译为c++或java

如何将ocaml代码编译为供C ++使用的本机

我可以将AS3代码或Flex项目交叉编译为本机C ++吗?

使用 emcc 将 C++ 代码编译为 WASM 的问题