2

我正在尝试让 PhysX 使用 Ubuntu 工作。

首先,我在这里下载了 SDK:


接下来,我提取了文件并安装了每个包:

dpkg -i filename.deb

这给了我位于 /usr/lib/PhysX/v2.8.1 中的以下文件:

  • libNxCharacter.so
  • libNxCooking.so
  • libPhysXCore.so
  • libNxCharacter.so.1
  • libNxCooking.so.1
  • libPhysXCore.so.1

接下来,我创建了指向 /usr/lib 的符号链接:

sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCharacter.so.1 /usr/lib/libNxCharacter.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCooking.so.1 /usr/lib/libNxCooking.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libPhysXCore.so.1 /usr/lib/libPhysXCore.so.1

现在,使用 Eclipse,我指定了以下库 (-l):

  • libNxCharacter.so.1
  • libNxCooking.so.1
  • libPhysXCore.so.1

以下搜索路径以防万一(-L):

  • /usr/lib/PhysX/v2.8.1
  • /usr/lib

此外,正如 Gerald Kaszuba 所建议的,我添加了以下包含路径 (-I):

  • /usr/lib/PhysX/v2.8.1
  • /usr/lib

然后,我尝试编译以下代码:

#include "NxPhysics.h"

NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
NxVec3 gDefaultGravity(0,-9.8,0);

void InitNx()
{
    gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);

    if (!gPhysicsSDK)
    {
        std::cout<<"Error"<<std::endl;
        return;
    }

    NxSceneDesc sceneDesc;
    sceneDesc.gravity = gDefaultGravity;
    gScene = gPhysicsSDK->createScene(sceneDesc);
}

int main(int arc, char** argv)
{
    InitNx();

    return 0;
}

我得到的第一个错误是:

NxPhysics.h:没有这样的文件或目录

这告诉我该项目显然没有正确链接。谁能告诉我我做错了什么,或者我还需要做什么才能让我的项目编译?我正在使用 GCC C++ 编译器。提前致谢!

4

3 回答 3

2

看起来您将头文件与库文件混淆了。NxPhysics.h 是一个源代码头文件。编译源代码时需要头文件(链接时不需要)。它可能位于 /usr/include 或 /usr/include/PhysX/v2.8.1 或类似位置。正如 Gerald Kaszuba 建议的那样,找到这个文件的真实位置并确保使用 -I 选项告诉编译器它在哪里。

链接编译的目标文件时(而不是编译时)需要这些库。稍后您需要使用 -L 和 -l 选项来处理这个问题。

注意:根据您调用 gcc 的方式,您可以让它编译然后通过单个调用链接,但在幕后它仍然执行编译步骤然后是链接步骤。


编辑:添加了额外的解释......

使用 C/C++ 编译器构建二进制文件时,编译器会读取源代码(.c 或 .cpp 文件)。在阅读它时,经常会出现用于读取 .h 文件的 #include 语句。#include 语句给出了必须加载的文件的名称。这些确切的文件必须存在于包含路径中。在您的情况下,必须在包含路径中的某处找到具有确切名称“NxPhysics.h”的文件。通常,/usr/include 默认位于路径中,当前目录也是如此。如果头文件位于其他位置,例如 /usr/include 的子目录,那么您始终需要使用 -I 命令行开关(或有时使用环境变量或其他系统配置方法)明确告诉编译器在哪里查找。

.h 头文件通常包括数据结构声明、内联函数定义、函数和类声明以及#define 宏。编译完成后,会创建一个 .o 目标文件。编译器不知道 .so 或 .a 库并且不能以任何方式使用它们,除了为链接器嵌入一点帮助信息。请注意,编译器还在目标文件中嵌入了一些“头”信息。我将“标题”放在引号中,因为该信息仅大致对应于 .h 文件中可能存在或不存在的内容。它包括所有导出声明的二进制表示。那里没有找到宏。我相信内联函数也被省略了(尽管我可能错了)。

一旦所有 .o 文件都存在,就该由另一个程序接管了:链接器。链接器对源代码文件或 .h 头文件一无所知。它只关心二进制库和目标文件。你给它一个库和目标文件的集合。在他们的“标题”中,他们列出了他们定义的内容(数据类型、函数等)以及他们需要其他人定义的内容。然后,链接器将来自一个模块的定义请求与其他模块的实际定义进行匹配。它会检查以确保没有多个冲突的定义,并且如果构建可执行文件,它会确保满足所有对定义的请求。

上述描述有一些值得注意的警告。首先,可以调用一次 gcc 并让它同时进行编译和链接,例如

gcc hello.c -o hello

将首先将 hello.c 编译到内存或临时文件,然后将链接到标准库并写出 hello 可执行文件。尽管它只是对 gcc 的一次调用,但为了方便您,这两个步骤仍然按顺序执行。我现在将跳过描述动态库的一些细节。

如果您是 Java 程序员,那么上面的一些内容可能会有点令人困惑。我相信 .net 像 Java 一样工作,所以下面的讨论应该适用于 C# 和其他 .net 语言。Java 在语法上是一种比 C 和 C++ 简单得多的语言。它缺少宏,也缺少真正的模板(泛型是模板的一种非常弱的形式)。因此,Java 不需要单独的声明 (.h) 和定义 (.c) 文件。它还能够将所有相关信息嵌入到目标文件(Java 的.class)中。这使得编译器和链接器都可以直接使用 .class 文件。

于 2009-01-06T04:38:18.600 回答
0

问题确实出在我的包含路径上。以下是相关命令:

g++ -I/usr/include/PhysX/v2.8.1/SDKs/PhysXLoader/include -I/usr/include -I/usr/include/PhysX/v2.8.1/LowLevel/API/include -I/usr/include/PhysX/v2.8.1/LowLevel/hlcommon/include -I/usr/include/PhysX/v2.8.1/SDKs/Foundation/include -I/usr/include/PhysX/v2.8.1/SDKs/Cooking/include -I/usr/include/PhysX/v2.8.1/SDKs/NxCharacter/include -I/usr/include/PhysX/v2.8.1/SDKs/Physics/include -O0 -g3 -DNX_DISABLE_FLUIDS -DLINUX -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"

此外,对于链接器,只需要“PhysXLoader”(与 Windows 相同)。因此,我有:

g++  -o"PhysXSetupTest"  ./main.o   -lglut -lPhysXLoader
于 2009-01-06T08:17:26.380 回答
0

安装时出现以下错误 *

dpkg: dependency problems prevent configuration of libphysx-dev-2.8.1:
 libphysx-dev-2.8.1 depends on libphysx-2.8.1 (= 2.8.1-4); however:
  Package libphysx-2.8.1 is not configured yet.
dpkg: error processing libphysx-dev-2.8.1 (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:

* 所以我重新安装了 *libphysx-2.8.1_4_i386.deb*

sudo dpkg -i libphysx-2.8.1_4_i386.deb 
于 2011-02-22T18:35:21.477 回答