【问题标题】:Building a C DLL compatible with Dreamweaver构建与 Dreamweaver 兼容的 C DLL
【发布时间】:2023-03-06 16:02:01
【问题描述】:

我引用的文档在这里,并且非常简短且切中要害: http://livedocs.adobe.com/en_US/Dreamweaver/9.0_API/help.html?content=dwr_sourcecontrol_so_01.html

我遇到的问题是我不确定如何编译实际的 DLL。 adobe 扩展论坛上的最后一个回复是 3 个月大,我不知道该去哪里问这个问题。

让我困惑的编程部分是我必须使用 C++ 构建 DLL,但大多数教程都是基于构建目标应用程序包含的头文件。 (我是 DLL 编程的新手。)Dreamweaver 只需要一个 DLL,它已经知道它将调用什么。我对如何将这些信息单独放在 DLL 文件中感到困惑,尽管基于我读过的教程,因为应用程序似乎也需要头文件或 lib 文件。

我第一次尝试使用 VS2008 并为我的项目类型选择了 win32 DLL,然后在它生成的导出函数文件中添加了所需的函数。我的第一个如下:

extern "C" __declspec(dllexport) bool SCS_Connect(void **connectionData, const char siteName[64])
{
 return true;
}

任何人都可以帮助澄清这是如何工作的吗?

编辑: 重读文档我注意到它说:

Dreamweaver 确定哪些功能 该库通过调用支持 每个 API 的 GetProcAddress() 功能。如果地址不 存在,Dreamweaver 假定库 不支持 API。如果 地址存在,Dreamweaver 使用 库的函数版本 支持功能。

虽然我仍然不确定这对于我的 DLL 编译意味着什么。

编辑 2: Dependency Walker 返回:

LoadLibraryW("c:\program files\adobe\adobe dreamweaver cs3\Configuration\SourceControl\mercFlow.dll") returned 0x05110000.
GetProcAddress(0x05110000 [MERCFLOW.DLL], "MM_InitWrapper") called from "DREAMWEAVER.EXE" at address 0x00D73D4B and returned NULL. Error: The specified procedure could not be found (127).
GetProcAddress(0x05110000 [MERCFLOW.DLL], "SCS_GetAgentInfo") called from "DREAMWEAVER.EXE" at address 0x00D73D66 and returned NULL. Error: The specified procedure could not be found (127).
GetProcAddress(0x05110000 [MERCFLOW.DLL], "SCS_GetNumNewFeatures") called from "DREAMWEAVER.EXE" at address 0x00D73D72 and returned NULL. Error: The specified procedure could not be found (127).
GetProcAddress(0x05110000 [MERCFLOW.DLL], "SCS_GetNewFeatures") called from "DREAMWEAVER.EXE" at address 0x00D73D7E and returned NULL. Error: The specified procedure could not be found (127).
GetProcAddress(0x05110000 [MERCFLOW.DLL], "SCS_Connect") called from "DREAMWEAVER.EXE" at address 0x00D73E2B and returned NULL. Error: The specified procedure could not be found (127).

其中一些是在我的 DLL 中定义的(根据文档,有些是可选的),但没有找到。这是否意味着我的函数没有被导出?

这是我的 DLL 源代码:

dllheader.h

#ifndef DLLHEADER_H_INCLUDED
#define DLLHEADER_H_INCLUDED
#ifdef DLL_EXPORT
# define EXPORT extern "C" __declspec (dllexport)
#else
# define EXPORT
#endif
DLL_EXPORT struct itemInfo;
DLL_EXPORT bool SCS_GetAgentInfo(char name[32],char version[32], char description[256], const char * dwAppVersion);
DLL_EXPORT bool SCS_Connect(void **connectionData, const char siteName[64]);
DLL_EXPORT bool SCS_Disconnect(void *connectionData);
DLL_EXPORT bool SCS_IsConnected(void *connectionData);
DLL_EXPORT int SCS_GetRootFolder_Length(void *connectionData);
DLL_EXPORT int SCS_GetFolderListLength(void *connectionData, const char *remotePath);
DLL_EXPORT bool SCS_GetFolderList(void *connectionData, const char *remotePath, itemInfo itemList[ ], const int numItems);
DLL_EXPORT bool SCS_Get(void *connectionData, const char *remotePathList[], const char *localPathList[], const int numItems);
DLL_EXPORT bool SCS_Put(void *connectionData, const char *localPathList[], const char *remotePathList[], const int numItems);
DLL_EXPORT bool SCS_NewFolder(void *connectionData,const char *remotePath);
DLL_EXPORT bool SCS_Delete(void *connectionData, const char *remotePathList[],const int numItems);
DLL_EXPORT bool SCS_Rename(void *connectionData, const char * oldRemotePath, const char*newRemotePath);
DLL_EXPORT bool SCS_ItemExists(void *connectionData,const char *remotePath);
#endif

ma​​in.cpp

#define DLL_EXPORT
#include "dllheader.h"
#include <iostream>
char* const gName="MercFlow";
char* const gVersion="1.0";
char* const gDescription="Native Mercurial Support for Dreamweaver.";


DLL_EXPORT struct itemInfo
{
    bool isFolder;
    int month;
    int day;
    int year;
    int hour;
    int minutes;
    int seconds;
    char type[256];
    int size;
};


// Description: This function asks the DLL to return its name and description, which appear in the Edit Sites dialog box. The name appears in the Server Access pop-up menu (for example, sourcesafe, webdav, perforce) and the description below the pop-up menu.
// name: The name argument is the name of the source control system. The name appears in the combo box for selecting a source control system on the Source Control tab in the Edit Sites dialog box. The name can be a maximum of 32 characters. 
DLL_EXPORT bool SCS_GetAgentInfo(char name[32],char version[32], char description[256], const char * dwAppVersion)
{
    name=gName;
    version=gVersion;
    description=gDescription;
    return true;
}
//Description: This function connects the user to the source control system. If the DLL does not have log-in information, the DLL must display a dialog box to prompt the user for the information and must store the data for later use.
DLL_EXPORT bool SCS_Connect(void **connectionData, const char siteName[64])
{
    return true;
}
DLL_EXPORT bool SCS_Disconnect(void *connectionData)
{
    return true;
}
DLL_EXPORT bool SCS_IsConnected(void *connectionData)
{
    return true;
}
DLL_EXPORT int SCS_GetRootFolder_Length(void *connectionData)
{
    return 0;
}
DLL_EXPORT bool SCS_GetRootFolder(void *connectionData, char remotePath[],const int folderLen)
{
    return true;
}
DLL_EXPORT int SCS_GetFolderListLength(void *connectionData, const char *remotePath)
{
    return 0;
}
DLL_EXPORT bool SCS_GetFolderList(void *connectionData, const char *remotePath, itemInfo itemList[ ], const int numItems)
{
    return true;
}
DLL_EXPORT bool SCS_Get(void *connectionData, const char *remotePathList[], const char *localPathList[], const int numItems)
{
    return true;
}
DLL_EXPORT bool SCS_Put(void *connectionData, const char *localPathList[], const char *remotePathList[], const int numItems)
{
    return true;
}
DLL_EXPORT bool SCS_NewFolder(void *connectionData,const char *remotePath)
{
    return true;
}
DLL_EXPORT bool SCS_Delete(void *connectionData, const char *remotePathList[],const int numItems)
{
    return true;
}
DLL_EXPORT bool SCS_Rename(void *connectionData, const char * oldRemotePath, const char*newRemotePath)
{
    return true;
}
DLL_EXPORT bool SCS_ItemExists(void *connectionData,const char *remotePath)
{
    return true;
}

【问题讨论】:

  • 目标应用程序仅包含一个标头/链接一个用于自动链接的库。通过 GetProcAddress 手动链接不需要任何此类 - 您可以在随机 DLL 上调用 GetProcAddress 并查找函数。
  • 当您尝试编译时会发生什么情况,您是否收到错误消息?
  • 编译成功。我很容易编译。它只是编译它,以便 Dreamweaver 可以正确查看函数。

标签: c++ c dll


【解决方案1】:

根据文档,您可能需要在 Dreamwaver 接受您的 DLL 之前添加所有必需的函数。您可以使用Dependency Walker 的配置文件模式来查看当 DW 加载您的 DLL 时会发生什么。并且还要验证您的 DLL 是否确实导出了所有必需的符号。

编辑:在 Dependency Walker 的模块树或模块列表中选择您的 DLL,然后查看右侧的导出列表(它在第一列标题中显示“E”)并确保所有必需的函数都在那里。如果 GetProcessAddress 在所需函数之一上失败,则需要添加该函数。

【讨论】:

  • 这是个好主意,但我相信 Dreamweaver 正在使用 Dependency Walker 所称的延迟加载依赖模块。对于 API DLL。直到我在 Dreamweaver 中转到站点>新站点后,才真正发生错误(尝试加载)。
  • 啊,我现在看到了。现在看着它......我希望我能再次投票给你。这很有帮助。
  • 我刚刚编辑了我的回复,希望这是在 SO 上做事的正确方法 :)
  • 不,他们没有出现。该列表是空的:(看来我搞砸了“添加”或导出的功能。
  • 我明白了!我使用了该项目的不同版本,发现我的一个名字有一个额外的下划线,这是一个必需的功能。太感谢了! Dependency Walker 非常完美!
猜你喜欢
  • 2020-04-12
  • 1970-01-01
  • 2010-12-31
  • 2012-11-09
  • 2020-04-23
  • 1970-01-01
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多