- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
你能在你的代码中调用一个没有主体但在头文件中声明的函数吗?请阅读下面我的情况。
我正在学习 C++,所以如果我的术语不合时宜,你就知道为什么了。无论如何,我正在阅读这本名为“高级 2D 游戏开发”的书,所以如果有人读过这本书,那么也许他们可以帮助我。在c++中他在Advanced2D.h中设置了4个extern函数
extern bool game_preload();
extern bool game_init(HWND);
extern void game_update();
extern void game_end();
后来,他在类里面多次拜访他们,但从未给他们一个 body 。他最终尝试将所有代码编译成 lib 文件,以便其他项目可以包含它并实际使用这 4 种方法。
他要我转到解决方案属性/常规/输出目录并将其添加到发布和调试配置中
$(ProjectDir)..\lib\Advance2D.lib // It didn't work. Still added the libs at default location
只有在像这样的另一个项目中使用上面的那些方法。这是声明性方法获得主体的时候。
#include <iostream>
#include "..\Engine\Advanced2D.h"
bool game_preload()
{
//display engine version in a message box
g_engine->message(g_engine->getVersionText(), "TEST ENGINE");
//return fail to terminate the engine
return false;
}
bool game_init(HWND hwnd) { return 0;}
void game_update() {}
void game_end() {}
现在唯一的问题是我收到链接器错误
1>winmain.obj : error LNK2019: unresolved external symbol "bool __cdecl game_preload(void)" (?game_preload@@YA_NXZ) referenced in function _WinMain@16
1>c:\Engine\msvc8\Advance2D\Advance2D\..\lib\Advance2D.lib\Advance2D.exe : fatal error LNK1120: 1 unresolved externals
如果我不注释掉第一个项目中使用的那些方法,那么该项目永远不会被编译?
那家伙坚持认为我在编译时不应收到任何链接器错误。我引用以下内容
Assuming you have typed the code into the specified files without any mistakes, you should be able to compile the engine project. There should be no dependencies for the engine because the compiler assumes that you will provide the needed libs at link time (when you create an executable using the engine’s lib). This is a rather complex issue that we’ll examine again over the next several chapters as we enhance the engine with new modules and functionality. You should not see any linker errors, only compiler errors if you have made a mistake while typing in the code.
下面是advanced2D header
// Advanced2D Engine
// Main header file
#ifndef _ADVANCED2D_H
#define _ADVANCED2D_H 1
#include <iostream>
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dxerr.h>
#include "Timer.h"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define REVISION 0
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib, "winmm.lib")
//external variables and functions
extern bool gameover;
extern bool game_preload();
extern bool game_init(HWND);
extern void game_update();
extern void game_end();
namespace Advanced2D
{
class Engine {
private:
int p_versionMajor, p_versionMinor, p_revision;
HWND p_windowHandle;
LPDIRECT3D9 p_d3d;
LPDIRECT3DDEVICE9 p_device;
LPDIRECT3DSURFACE9 p_backbuffer;
LPD3DXSPRITE p_sprite_handler;
std::string p_apptitle;
bool p_fullscreen;
int p_screenwidth;
int p_screenheight;
int p_colordepth;
bool p_pauseMode;
D3DCOLOR p_ambientColor;
bool p_maximizeProcessor;
Timer p_coreTimer;
long p_frameCount_core;
long p_frameRate_core;
Timer p_realTimer;
long p_frameCount_real;
long p_frameRate_real;
public:
Engine();
virtual ~Engine();
int Init(int width, int height, int colordepth, bool fullscreen);
void Close();
void Update();
void message(std::string message, std::string title = "ADVANCED 2D");
void fatalerror(std::string message, std::string title = "FATAL ERROR");
void Shutdown();
void ClearScene(D3DCOLOR color);
void SetDefaultMaterial();
void SetAmbient(D3DCOLOR colorvalue);
int RenderStart();
int RenderStop();
int Release();
//accessor/mutator functions expose the private variables
bool isPaused() { return this->p_pauseMode; }
void setPaused(bool value) { this->p_pauseMode = value; }
LPDIRECT3DDEVICE9 getDevice() { return this->p_device; }
LPDIRECT3DSURFACE9 getBackBuffer() { return this->p_backbuffer; }
LPD3DXSPRITE getSpriteHandler() { return this->p_sprite_handler; }
void setWindowHandle(HWND hwnd) { this->p_windowHandle = hwnd; }
HWND getWindowHandle() { return this->p_windowHandle; }
std::string getAppTitle() { return this->p_apptitle; }
void setAppTitle(std::string value) { this->p_apptitle = value; }
int getVersionMajor() { return this->p_versionMajor; }
int getVersionMinor() { return this->p_versionMinor; }
int getRevision() { return this->p_revision; }
std::string getVersionText();
long getFrameRate_core() { return this->p_frameRate_core; };
long getFrameRate_real() { return this->p_frameRate_real; };
int getScreenWidth() { return this->p_screenwidth; }
void setScreenWidth(int value) { this->p_screenwidth = value; }
int getScreenHeight() { return this->p_screenheight; }
void setScreenHeight(int value) { this->p_screenheight = value; }
int getColorDepth() { return this->p_colordepth; }
void setColorDepth(int value) { this->p_colordepth = value; }
bool getFullscreen() { return this->p_fullscreen; }
void setFullscreen(bool value) { this->p_fullscreen = value; }
bool getMaximizeProcessor() { return this->p_maximizeProcessor; }
void setMaximizeProcessor(bool value) { this->p_maximizeProcessor = value;}
}; //class
}; //namespace
//define the global engine object (visible everywhere!)
extern Advanced2D::Engine *g_engine;
#endif
Advanced2d 类
// Advanced2D Engine
// Main source code file
//includes
#include "Advanced2D.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <sstream>
#include <list>
#include "winmain.h"
namespace Advanced2D
{
Engine::Engine()
{
srand((unsigned int)time(NULL));
p_maximizeProcessor = false;
p_frameCount_core = 0;
p_frameRate_core = 0;
p_frameCount_real = 0;
p_frameRate_real = 0;
p_ambientColor = D3DCOLOR_RGBA(255,255,255, 0);
p_windowHandle = 0;
p_pauseMode = false;
p_versionMajor = VERSION_MAJOR;
p_versionMinor = VERSION_MINOR;
p_revision = REVISION;
//set default values
this->setAppTitle("Advanced2D");
this->setScreenWidth(640);
this->setScreenHeight(480);
this->setColorDepth(32);
this->setFullscreen(false);
//window handle must be set later on for DirectX!
this->setWindowHandle(0);
}
Engine::~Engine()
{
if (this->p_device) this->p_device->Release();
if (this->p_d3d) this->p_d3d->Release();
}
std::string Engine::getVersionText()
{
std::ostringstream s;
s << "Advanced2D Engine v" << p_versionMajor << "." << p_versionMinor
<< "." << p_revision;
return s.str();
}
void Engine::message(std::string message, std::string title)
{
MessageBox(0, message.c_str(), title.c_str(), 0);
}
void Engine::fatalerror(std::string message, std::string title)
{
this->message(message,title);
Shutdown();
}
int Engine::Init(int width, int height, int colordepth, bool fullscreen)
{
//initialize Direct3D
this->p_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (this->p_d3d == NULL) {
return 0;
}
//get system desktop color depth
D3DDISPLAYMODE dm;
this->p_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);
//set configuration options for Direct3D
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.BackBufferFormat = dm.Format;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = p_windowHandle;
//create Direct3D device
this->p_d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
this->p_windowHandle,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp,
&this->p_device);
if (this->p_device == NULL) return 0;
//clear the backbuffer to black
this->ClearScene(D3DCOLOR_XRGB(0,0,0));
//create pointer to the back buffer
this->p_device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &this->p_backbuffer);
//use ambient lighting and z-buffering
this->p_device->SetRenderState(D3DRS_ZENABLE, TRUE);
this->p_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
this->SetAmbient(this->p_ambientColor);
//initialize 2D renderer
HRESULT result = D3DXCreateSprite(this->p_device, &this->p_sprite_handler);
if (result != D3D_OK) return 0;
//call game initialization extern function
//if (!game_init(this->getWindowHandle())) return 0;
//set a default material
SetDefaultMaterial();
return 1;
}
void Engine::SetDefaultMaterial()
{
D3DMATERIAL9 mat;
memset(&mat, 0, sizeof(mat));
mat.Diffuse.r = 1.0f;
mat.Diffuse.g = 1.0f;
mat.Diffuse.b = 1.0f;
mat.Diffuse.a = 1.0f;
p_device->SetMaterial(&mat);
}
void Engine::ClearScene(D3DCOLOR color)
{
this->p_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
color, 1.0f, 0);
}
void Engine::SetAmbient(D3DCOLOR colorvalue)
{
this->p_ambientColor = colorvalue;
this->p_device->SetRenderState(D3DRS_AMBIENT, this->p_ambientColor);
}
int Engine::RenderStart()
{
if (!this->p_device) return 0;
if (this->p_device->BeginScene() != D3D_OK) return 0;
return 1;
}
int Engine::RenderStop()
{
if (!this->p_device) return 0;
if (this->p_device->EndScene() != D3D_OK) return 0;
if (p_device->Present(NULL, NULL, NULL, NULL) != D3D_OK) return 0;
return 1;
}
void Engine::Shutdown()
{
gameover = true;
}
void Engine::Update()
{
static Timer timedUpdate;
//calculate core framerate
p_frameCount_core++;
if (p_coreTimer.stopwatch(999)) {
p_frameRate_core = p_frameCount_core;
p_frameCount_core = 0;
}
//fast update with no timing
game_update();
//update with 60fps timing
if (!timedUpdate.stopwatch(14)) {
if (!this->getMaximizeProcessor())
{
Sleep(1);
}
}
else {
//calculate real framerate
p_frameCount_real++;
if (p_realTimer.stopwatch(999)) {
p_frameRate_real = p_frameCount_real;
p_frameCount_real = 0;
}
//begin rendering
this->RenderStart();
//done rendering
this->RenderStop();
}
}
void Engine::Close()
{
game_end();
}
} //namespace
这是 WinMain
#include <sstream>
#include "winmain.h"
#include "Advanced2D.h"
//macro to read the key states
#define KEY_DOWN(vk) ((GetAsyncKeyState(vk) & 0x8000)?1:0)
HINSTANCE g_hInstance;
HWND g_hWnd;
int g_nCmdShow;
//declare global engine object
Advanced2D::Engine *g_engine;
bool gameover;
//window event callback function
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_QUIT:
case WM_CLOSE:
case WM_DESTROY:
gameover = true;
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int
nCmdShow)
{
MSG msg;
srand((unsigned int)time(NULL));
g_hInstance = hInstance;
g_nCmdShow = nCmdShow;
DWORD dwStyle, dwExStyle;
RECT windowRect;
/**
* Create engine object first!
**/
g_engine = new Advanced2D::Engine();
//let main program have a crack at things before window is created
if (!game_preload()) {
MessageBox(g_hWnd, "Error in game preload!", "Error", MB_OK);
return 0;
}
//get window caption string from engine
char title[255];
sprintf_s(title, "%s", g_engine->getAppTitle().c_str());
//set window dimensions
windowRect.left = (long)0;
windowRect.right = (long)g_engine->getScreenWidth();
windowRect.top = (long)0;
windowRect.bottom = (long)g_engine->getScreenHeight();
//create the window class structure
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
//fill the struct with info
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = title;
wc.hIconSm = NULL;
//set up the window with the class info
RegisterClassEx(&wc);
//set up the screen in windowed or fullscreen mode?
if (g_engine->getFullscreen())
{
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
dm.dmPelsWidth = g_engine->getScreenWidth();
dm.dmPelsHeight = g_engine->getScreenHeight();
dm.dmBitsPerPel = g_engine->getColorDepth();
dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
g_engine->setFullscreen(false);
}
dwStyle = WS_POPUP;
dwExStyle = WS_EX_APPWINDOW;
ShowCursor(FALSE);
}
else {
dwStyle = WS_OVERLAPPEDWINDOW;
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
}
//adjust window to true requested size
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
//create the program window
g_hWnd = CreateWindowEx( 0,
title, //window class
title, //title bar
dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, //x,y coordinate
windowRect.right - windowRect.left, //width of the window
windowRect.bottom - windowRect.top, //height of the window
0, //parent window
0, //menu
g_hInstance, //application instance
0); //window parameters
//was there an error creating the window?
if (!g_hWnd) {
MessageBox(g_hWnd, "Error creating program window!", "Error", MB_OK);
return 0;
}
//display the window
ShowWindow(g_hWnd, g_nCmdShow);
UpdateWindow(g_hWnd);
//initialize the engine
g_engine->setWindowHandle(g_hWnd);
if (!g_engine->Init(g_engine->getScreenWidth(), g_engine->getScreenHeight(),
g_engine->getColorDepth(), g_engine->getFullscreen())) {
MessageBox(g_hWnd, "Error initializing the engine", "Error", MB_OK);
return 0;
}
// main message loop
gameover = false;
while (!gameover)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
g_engine->Update();
}
if (g_engine->getFullscreen()) {
ShowCursor(TRUE);
}
g_engine->Close();
delete g_engine;
return 1;
}
最佳答案
extern
关键字指定该函数将在您所在的编译对象外部的编译对象中实现 - 通常通过 lib 或其他对象。如果您要在一个 cpp 文件中(在任何函数体之外)在全局范围内声明一个变量,您只能在另一个 cpp 文件中使用外部 {variable declaration} 引用它 - 这样编译器就知道不要期望函数/变量被定义但知道它存在。
这里发生的事情的声音是你链接到的对象实际上并没有被链接——它应该是。上面的答案告诉你如何——我不够快!从您的问题看来,您似乎拥有第二个项目的源代码并且可能需要自己构建它 - 当然我不知道,但是如果 .lib 不存在那么您将需要。
关于c++ - 可以在没有主体的情况下调用声明的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2323901/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!