0

我的 cmd.exe环境控制台输出

Microsoft Windows [10.0.15063.1112]
(c) 2017 Microsoft Corporation

C:\Users\>py -3
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

C:\Users\>py -2
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
E:\TDM-GCC-64\bin>gcc --version
gcc (tdm64-1) 5.1.0
Copyright (C) 2015 Free Software Foundation, Inc.

如下控制台输出所示,我使用了两个版本的 python。我使用 Code::Blocks 16.01 创建了一个 DLL 项目,该项目使用 GNU GCC 编译器的 TDM-GCC(代码块中包含的 GNU GCC 编译器无法构建 x86_64 程序,它构建的 x86 dll 导致 WindowsError:[Error 193 ] 使用以下代码加载时)

python代码在这里(testdll.py)

import ctypes
DLL_PATH = './testdll.dll'
lib = ctypes.WinDLL(DLL_PATH) 
# or #lib = ctypes.cdll.LoadLibrary(DLL_PATH) 
#didn't work in python3.6
print("dll loaded")
lib.SomeFunction(b"12345")

dll c++ 代码(主要由代码块生成)

#include "main.h"
#include <cstring>

using namespace std;

// a sample exported function
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{

    volatile char* aaa = new char[100];
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
        default:
            break;
    }
    return TRUE; // succesful
}

char* bar(char* a, char* b)//the only function i added, which was copied from someone's blog
{
    char* out = new char[strlen(a) + strlen(b) + 1];
    strcpy(out, a);
    strcat(out, b);
    return out;
}

这是main.h

#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>

/*  To use this exported function of dll, include this header
 *  in your project.
 */

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C"
{
#endif

void DLL_EXPORT SomeFunction(const LPCSTR sometext);

#ifdef __cplusplus
}
#endif

#endif // __MAIN_H__

DLL 编译选项(构建日志)

-------------- Build: Release in testdll (compiler: TDM-GCC of GNU GCC Compiler)---------------
[ 50.0%] g++.exe -m64 -Wall -DBUILD_DLL -O2 -Wshadow -Winit-self -Winline -Wswitch-default -Wmain -Wfatal-errors -std=c++11 -g -Weffc++ -Wextra -Wall -Wno-comment -DLOCAL -IE:\TDM-GCC-64\include -c Y:\testdll\main.cpp -o obj\Release\main.o
[100.0%] g++.exe -shared -Wl,--output-def=bin\Release\libtestdll.def -Wl,--out-implib=bin\Release\libtestdll.a -Wl,--dll -LE:\TDM-GCC-64\lib obj\Release\main.o  -o bin\Release\testdll.dll -m64 -s  -luser32

问题

使用时py -2 testdll.py,它工作正常并得到消息框和控制台日志“加载了dll”,但是使用时python -3 testdll.py,这是回溯。

Y:\testdll\bin\Release>py -3 testdll.py
Traceback (most recent call last):
  File "testdll.py", line 10, in <module>
    lib = ctypes.WinDLL(DLL_PATH)
  File "E:\Python36x64\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 1114]

当我从 c++ 代码中删除该函数(下面的代码)时,单击重建按钮,使用 Python2 或 Python3 重新运行 python 代码,它都可以正常工作并得到正确的输出。

char* bar(char* a, char* b)//the only function i added, which was copied from someone
{
    char* out = new char[strlen(a) + strlen(b) + 1];// after some test, I think
                                                    // this line caused this problem
                                                    // using such as 
                                                    //volatile char *ppp=new char[66];
                                                    // will cause the dll file become 100kB+ larger and can't be loaded by Python 3.6 
                                                    // ##(some strange thing happens, when I rerun this, this function no longer matters, it can't be loaded by Python3.6 anyways)##
    strcpy(out, a);
    strcat(out, b);
    return out;
}

谁能告诉我为什么,谢谢,我真的很困惑。

我刚刚重新运行了这些步骤(使用命令行而不是代码块)

1、复制上面贴的代码(并保存在某处)
2、打开cmd.exe
3、运行以下命令(并将输出粘贴到这里)

Y:\tmp>g++.exe -m64 -Wall -DBUILD_DLL -O2 -Wshadow -Winit-self -Winline -Wswitch-default -Wmain -Wfatal-errors -std=c++11 -g -Weffc++ -Wextra -Wall -Wno-comment -DLOCAL -IE:\TDM-GCC-64\include -c main.cpp -o main.o
main.cpp: In function 'BOOL DllMain(HINSTANCE, DWORD, LPVOID)':
main.cpp:15:20: warning: unused variable 'aaa' [-Wunused-variable]
     volatile char* aaa = new char[100];
                    ^
main.cpp: At global scope:
main.cpp:12:55: warning: unused parameter 'hinstDLL' [-Wunused-parameter]
 extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
                                                       ^
main.cpp:12:89: warning: unused parameter 'lpvReserved' [-Wunused-parameter]
 extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
                                                                                         ^

Y:\tmp>g++.exe -shared -Wl,--output-def=libtestdll.def -Wl,--out-implib=libtestdll.a -Wl,--dll -LE:\TDM-GCC-64\lib main.o  -o testdll.dll -m64 -s  -luser32

4、重新运行 py -3 testdll.py 仍然出现 OSError: [WinError 1114] 但是这一次,我删除了上面提到的那个函数,Python3.6 仍然拒绝加载那个 dll,:(

5、检查py -3py -2gcc --version确认版本不变

我的解决方案

虽然将 CodeBlocks 生成的项目编译到 WinDll 不成功;我尝试使用以下命令将手动编写的源代码编译为 cdll 以获得本机速度(但不能使用某些宏,例如DLL_EXPORT)。

$(GCC) $< -o $@ -I $(SRC_DIR)/common/crapto1/ -Wl,crapto1.dll -shared
g++ test.cpp -o test.dll -shared
etc.

下面的代码由我的g++和py2、py3编译加载成功。

#include <cstdio>
#include <windows.h>
using namespace std;
extern "C" int foo();
int foo(){
  printf("This Works!\n");
  MessageBoxA(0, "This Works!", "DLL Message", MB_OK | MB_ICONINFORMATION);
  return 0;
}
//ctypes.WinDLL(DLL_PATH).foo()
//ctypes.cdll.LoadLibrary(DLL_PATH).foo() #both works fine in Python 2 and Python 3
4

0 回答 0