gpt4 book ai didi

c++ - 如何在执行 LoadLibrary ("*.exe"时初始化 CRT)

转载 作者:太空宇宙 更新时间:2023-11-04 04:48:15 25 4
gpt4 key购买 nike

我正在尝试将 numpy 数组传递给 C 并在那里进行一些计算。

我正在将可执行文件构建为 exe 并导出一些 Python 然后调用的函数。该过程有效,但我无法使用 printf() 等标准函数。如果我将二进制文件构建为 dll,它就可以工作。通过在互联网上搜索,我了解到 dll 加载和 exe 加载(maincrtstartup?)对运行时库进行初始化。是否可以复制他们所做的以便我可以使用 printf()

Python代码

import  numpy as np
import ctypes
from numpy.ctypeslib import ndpointer

lib = ctypes.cdll.LoadLibrary('pycon.exe')

fun = lib.fun
fun.restype = None
fun.argtypes = [ndpointer(ctypes.c_double),
ctypes.c_size_t]



data = np.ones((5,5)).astype('double')
def wfun(d):
fun(d, d.size)
print data
wfun(data)
print data

C代码

#include <stdio.h>
#include <math.h>
extern "C" __declspec(dllexport)
void fun(double *datav, size_t size) {
//printf("crash");
double * data = (double *) datav;
int i;
for (i = 0; i < size; ++i)
data[i] = 1.7159*tanh(0.66666667*data[i]);
}


extern "C" __declspec(dllexport)
void init() {
//what to put here?
}


int main(int argc, char* argv[])
{
return 0;
}

最佳答案

我已经意识到将 exe 视为 dll 比我想象的要复杂得多。我最终得到了以下解决方法。

python

import  numpy as np
import ctypes as C

lib = C.cdll.LoadLibrary('pycon.exe')
lib.init( C.windll.kernel32.GetProcAddress( C.windll.msvcrt._handle,'printf'))

d = np.ones((5)).astype('double')
lib.fun(d.ctypes.data_as(C.POINTER(C.c_double)), C.c_size_t(5))

c

#include <stdio.h>
#include <math.h>

int (*pyprintf)(const char *,...) =0;

extern "C" __declspec(dllexport)
void fun(double *datav, size_t size) {
double * data = (double *) datav;
int i;
for (i = 0; i < size; ++i)
{
data[i] = 1.7159*tanh(0.66666667*data[i]);
pyprintf("workign! %f\n",data[i]);
}
}

extern "C" __declspec(dllexport)
void init(int (*_printfPtr)(const char *,...)) {
pyprintf=_printfPtr;
}

int main(int argc, char* argv[])
{
printf("exe");
return 0;
}

编辑

好奇心战胜了我,兔子洞越来越大,现在它比上面的稍微不那么笨拙,似乎可以同时作为 exe 和 dll 运行,但加载代码更多一些。

要求

  • 'exe' 必须只依赖于 kernel32
  • 文件包
  • 链接器标志 /FIXED:NO -entry:_DllMainCRTStartup@12

python

import  numpy as np
import ctypes as C
import pefile

def unprotect( address):
crap = C.byref(C.create_string_buffer("\x00"*4))
res = C.windll.kernel32.VirtualProtect(address, 0x1000, 0x40, crap)

lib = C.cdll.LoadLibrary('pycon.exe')
k32 = C.windll.kernel32
pe = pefile.PE('pycon.exe')


for entry in pe.DIRECTORY_ENTRY_IMPORT:
#print entry.dll
#assuming that the exe only has dependency on kernel32
for imp in entry.imports:
diff = imp.address-0x400000
memptr = k32.GetProcAddress(k32._handle,imp.name)
unprotect(lib._handle+diff)
fptr = (C.c_uint).from_address(lib._handle+diff)
fptr.value = memptr

d = np.ones((5)).astype('double')
lib.init()
lib.fun(d.ctypes.data_as(C.POINTER(C.c_double)), C.c_size_t(5))
print d

c

#include <stdio.h>
#include <math.h>
#include <windows.h>

extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);

extern "C" __declspec(dllexport)
void fun(double *datav, size_t size) {
double * data = (double *) datav;
int i;
for (i = 0; i < size; ++i)
{
data[i] = 1.7159*tanh(0.66666667*data[i]);
printf("workign! %f\n",data[i]);
}
fflush(stdout);
}

extern "C" __declspec(dllexport)
void init() {
_CRT_INIT(NULL,DLL_PROCESS_ATTACH,NULL);
}


BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
_CRT_INIT(NULL,DLL_PROCESS_ATTACH,NULL);
printf("main exe");
return TRUE;
}

关于c++ - 如何在执行 LoadLibrary ("*.exe"时初始化 CRT),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18732513/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com