从DLL中导出ASM函数 - Visual Studio C++

4

我创建了一个Dll项目。 我创建了一个名为myasm.asm的文件,其中包含一个函数:

 .486
.model flat, stdcall
.code
MyProc1 proc x: DWORD, y: DWORD
    xor eax,eax
//......//
    ret
MyProc1 endp
    end

这里是我的头文件:
#pragma once

#include <Windows.h>

#ifdef LAB1DLL_EXPORTS
#define LAB1DLL_API __declspec(dllexport)
#else
#define LAB1DLL_API __declspec(dllimport)
#endif

extern "C"
{
    LAB1DLL_API int _stdcall MyProc1(DWORD x, DWORD y);
}

并且dllMain(它的开头)

#define LAB1DLL_EXPORTS 1
#include "Lab1Dll.h"

在我的测试应用程序中,我想要使用那个dll文件和它导出的函数,我有以下代码:
#include "Lab1Dll.h"

但我的dll没有导出MyProc1函数。 如果我向该DLL添加“普通”函数并将其导出,那么它就可以在我的Test应用程序中使用,并且DLL编译过程会生成lib文件。
如果没有“普通”函数,我就不会得到.lib文件。 我无法链接到该库。
如何使导出的函数起作用? 或者如何使其首先导出?
更新: 我看到添加以下内容的.def文件可以完美工作。 但是,我不应该这样做。 __declspec(dllexport)应该为我做到这一点?
LIBRARY

EXPORTS

MyProc1

可能与装饰/修饰过的名称有关,请使用 dumpbin 进行检查。尝试在 myasm.asm 中使用其装饰/修饰过的名称定义过程(但不要在头文件和 C 源文件中定义)。其他建议请参考:https://dev59.com/3XE85IYBdhLWcg3wYSZk - Ruud Helderman
@Ruud 怎么做?我在问那个“装饰”。 - Hooch
3个回答

3

在MASM中,与__declspec(dllexport)相对应的是在proc之后加上EXPORT

这样将会在MASM生成的*.obj文件中添加.drectve部分,并且会被链接器处理。

“Original Answer”翻译成中文是“最初的回答”。

.386
.model flat, stdcall
.code
MyProc1 proc EXPORT x: DWORD, y: DWORD
    xor eax,eax
    ret
MyProc1 endp
end

此外,如果您在头文件中将MyProc1声明为extern "C",则是这样的: MyProc1 proc C EXPORT x: DWORD, y: DWORD 否则就是这样的: MyProc1 proc stdcall EXPORT x: DWORD, y: DWORD 以确保名称混淆匹配。"Original Answer"的翻译是"最初的回答"。

好尴尬,没看到这是一个从2014年被顶起来的旧问题。 - PeterT
1
没问题。无论如何我都会回答它,知道这是一个老问题,尽管回答不是那么好(我没有意识到 PROC 有 EXPORT 关键字)。但我想补充一点,__declspec(dllexport) 对原始发布者不起作用的原因是它需要用于函数的定义,而不是声明。 - Ross Ridge
@RossRidge,由于您无法将*.h文件包含到*.asm文件中,因此dllexport无法与masm一起使用。此外,EXPORT的文档似乎并不是很完整,但我只是为了完整性而添加它。 - PeterT

3
当我尝试从另一个模块(DLL/EXE)中使用从DLL导出的程序集函数时,我遇到了类似的问题。通过链接错误,我发现导入模块正在尝试访问__impl_SRFlushCache函数,而不是在导出模块的头文件中声明并在汇编文件中定义的SRFlushCache函数。因此,无论如何我都声明了extern "C"以避免任何混淆,但仍然添加了__impl_前缀。
我通过向导出模块添加模块定义(.def)文件并在其中列出我的汇编函数来解决了这个问题,如下所示:
LIBRARY SRPlatform
EXPORTS
  SRFlushCache

供参考:

头文件中的函数声明:

#ifdef SRPLATFORM_EXPORTS
#define SRPLATFORM_API __declspec(dllexport)
#else
#define SRPLATFORM_API __declspec(dllimport)
#endif // SRPLATFORM_EXPORTS

SRPLATFORM_API void __fastcall SRFlushCache(const void *pFirstCl, const void *pLimCl, const size_t clSize);

在.asm文件中定义函数:
_DATA SEGMENT

_DATA ENDS

_TEXT SEGMENT

PUBLIC SRFlushCache

; RCX=pFirstCl
; RDX=pLimCl
; R8=clSize
SRFlushCache PROC

SRFlushCache_Loop:
  clflushopt byte ptr [RCX]
  add RCX, R8
  cmp RCX, RDX ; RCX-RDX
  jl SRFlushCache_Loop
  ret

SRFlushCache ENDP

_TEXT ENDS

END

在Visual Studio中,首先您需要在项目中创建一个包含定义的name.def文件。然后,进入项目属性 > 链接器 > 输入 > 模块定义文件。将name.def文件添加到该属性中。这样就可以导出了。(如果有人像我一样遇到如何将定义文件添加到项目中的问题。) - douggard

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接