VS中调用c在cygwin生成的dll,出现了调用崩溃

pingglala 2014-09-03 11:03:11
大家好,我现在有个问题,苦苦折腾了几天,还没解决,因此上来寻找知道问题的高手,先感谢所有进入看帖的人,下面进入正文:
我现在有个需求,需要将linux下的c程序作成dll,提供给windows平台的vs程序调用,代码实现跨平台。

一、采用的方式是:通过cygwin把c代码生成dll文件,然后在vs2005中动态载入dll,调用接口函数,具体做法如下:

1、cygwin中生成dll:
1) gcc -c mytest.c
2) gcc -shared -o mytest.dll mytest.o

2、mytest.dll和cygwin1.dll放到vs2005工程目录。
3、vs2005中调用(工程为MFC对话框工程):

1) 导入cygwin1.dll,初始化:
// code1:
//文件头部定义代码:
HMODULE h;
typedef int(*PFN_CYGWIN_INIT)();

// 工程入口载入cygwin1.dll
h = LoadLibrary(TEXT("cygwin1.dll"));
PFN_CYGWIN_INIT init = (PFN_CYGWIN_INIT)GetProcAddress(h, "cygwin_dll_init");
init();

2) 在工程需要的地方调用dll的方法,代码如下(FreeLibrary没写出来):
// code2:
//文件头部定义代码:
HMODULE hLib;
typedef int(*PFN_TIME)(int a, int b);
PFN_TIME getTime;

// 某个方法内调用
hLib = LoadLibrary(TEXT("mytest.dll"));
getTime = (PFN_TIME)GetProcAddress(h, "Add_func");
long t = getTime(3, 5);

二、出现的问题:
1、code2紧跟在code1后面,程序正常调用,没有问题,code2放在工程中别的位置,有的地方可以,有的地方不行(貌似越靠程序流程前面,调用就会正常)。
2、现象:出问题的时候,有两种现象,他们是我把调用代码放在不同的地方出现的:一种是dll能正常调用,但发现在LoadLibrary之后,当前类的指针this就变成了0x00000000,退出当前函数,程序就崩溃;另一种情况是调试的时候,跟到long t = getTime(3, 5);这一行,程序就没有了反应,好像在里面出不来了,没往下执行了。

三、尝试过的方法:
1、官方说“Make sure you have 4K of scratch space at the bottom of your stack”,所以我在vs中也做了设置:“项目”属性->配置属性->链接器->系统,堆栈保留大小和堆栈提交大小设成了2097152和4096,对应十六进制100000,1000,这个值是经dumpbin /HEADERS mytest.dll查到的。
2、也试过在编译dll的时候在gcc中设置了上面的值,但也无济于事。

猜测:
1、“4K of scratch space”很可能是一个原因,但是不太清楚是否是这样设置;
2、会否是因为对话框程序在切换对话框后另启了一个线程,导致无法读到原来堆栈的bottom信息;
3、编译dll的时候是否还有别的option要加,因为奇怪的是:如果我的dll里面是一个简单的加法运算的方法,程序调用是完全没有问题的!但是我的dll源文件里面加入了<sys/time.h>用来做一个获取当前时间的方法,程序调用就出现了本文的问题。

希望在这里有缘碰到刚好在这方面有经验的朋友给予赐教,感谢你花时间看我的问题!
...全文
1444 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
jorhai 2015-11-08
  • 打赏
  • 举报
回复
楼主,有个问题请教下。 我把一个Linux下的库在cygwin下编译了, 然后想在MFC中调用,按照你的方法确实可以动态加载函数。 但是怎么解决头文件的问题呢?因为这个库有很多Linux下的头文件。
liuqincaijuan 2015-10-08
  • 打赏
  • 举报
回复
我也碰到类似问题,但还是没成功,具体是什么原因造成的?
pingglala 2014-10-07
  • 打赏
  • 举报
回复
wongkiongong,你好!太神奇了。我按照你说的思路去试了,在最后一步终于把程序调过了,Amazing!非常感谢您的建议!
wongkiongong 2014-09-27
  • 打赏
  • 举报
回复
建议从以下几个方面排除问题: 1、exe执行的工作目录与调试时是不一样的,要保证exe目录下都有project目录的一些库; 2、你项目中用到LoadLibrary,要判断是否取正常加载了dll,已经是否获取到了指针函数,还有dll依赖的dll也要拷贝到运行目录; 3、权限问题,看看以管理员身份执行是否可以,如果不行再提升进程权限,具体方法百度; 4、vs2005配置问题,属性->常规->MFC使用,“在静态库中使用MFC”,C/C++->代码生成->运行时库,"多线程 DLL (/MD)"。 5、打日志,跟进程序挂的位置。 6、你调用的dll中是否有日志输入的代码,有的话建议去掉。
pingglala 2014-09-24
  • 打赏
  • 举报
回复
oh my god! 原问题之前弄好了,可以在程序任意位置调用dll的方法。但是现在新的问题出现了,当我把工程编译成可执行文件后,双击执行程序,当到了dll方法调用的地方,程序就挂了。 有谁清楚debug/release与双击运行exe两者有什么区别和要注意的地方吗?特别是调用dll的时候。
pingglala 2014-09-24
  • 打赏
  • 举报
回复
oh my god! 之前那个问题弄好了,现在用双击执行的方式,每当运行到调用dll里面 的方法的时候,程序就退出了,折腾阿! 谁能告诉我debug/release与双击运行有什么要注意的地方?
wongkiongong 2014-09-22
  • 打赏
  • 举报
回复
Hey gey! I've ever encountered the problem like you,eventually I resolved it. I benefit from the website as: http://blog.csdn.net/null_shadow/article/details/1807797 Mind that:you should keep the stackbase alive,so that everytime you call the dll,you have the stack called, assembler would help you! Best luck!
pingglala 2014-09-05
  • 打赏
  • 举报
回复
问题已经解决了.在此先多谢micropentium6的关注.我后来采用cygwin64位的编译dll,没有报-fPIC ignored 的warning,但是仍无法解决问题.最后我是通过cygwin源码中的padding解决了问题.
pingglala 2014-09-04
  • 打赏
  • 举报
回复
引用 1 楼 micropentium6 的回复:
what if you isolate the method having the function call defined in sys/time.h? will it crash as well?
今天又重新试了,竟然发现在简单加法运算的dll中加入<sys/time.h>头文件,也可以正常使用,将加法运算换成时间运算后,程序就变得崩溃。 下面那个是OK的: #include <stdio.h> #include <sys/time.h> int AddFunc(int a, int b) { return a+b; //struct timeval tv; //gettimeofday(&tv, NULL); //return (int)(tv.tv_sec*100+tv.tv_usec); } 下面那个是崩溃的: #include <stdio.h> #include <sys/time.h> int AddFunc(int a, int b) { //return a+b; struct timeval tv; gettimeofday(&tv, NULL); return (int)(tv.tv_sec*100+tv.tv_usec); } 另:崩溃那个dll,我用gcc编译成exe是可以正常跑的。
pingglala 2014-09-04
  • 打赏
  • 举报
回复
引用 13 楼 micropentium6 的回复:
[quote=引用 12 楼 pingglala 的回复:] libtest.c:1: warning: -fPIC ignored for target (all code is position independent
interesting! I wonder if this is a default behavior of gcc for cygwin? as for ur question, I know windows and linux has some difference in terms of time handling. I bet cygwin/gcc messed it up...[/quote] 我换了一个不是处理时间的,程序也是不行. 顺便问一下你: 我现在做的通过VS调用cygwin生成的dll,是因为看了网上说这样做是可行的. quote: If you want to load the DLL dynamically, read winsup/cygwin/how-cygtls-works.txt and the sample code in winsup/testsuite/cygload to understand how this works. The short version is: 1.Make sure you have 4K of scratch space at the bottom of your stack. 2.Invoke cygwin_dll_init(): HMODULE h = LoadLibrary("cygwin1.dll"); void (*init)() = GetProcAddress(h, "cygwin_dll_init"); init(); 他上面的意思应该是4K of scratch 是保留用来load cygwin1.dll的吧,那会不会可能是没有办法设置足够多的stack来load我自己的dll? 因为我在同一个程序流程里面,只能执行一次,以下代码是先执行Oninit,然后点击是执行OnOk,代码如下: Oninit() { hd = LoadLibrary(TEXT("mytest.dll")); getTime = (PFN_TIME)GetProcAddress(hd, "Add_fun"); long d = getTime(1,2); } OnOk { //hd = LoadLibrary(TEXT("mytest.dll")); getTime = (PFN_TIME)GetProcAddress(hd, "Add_fun"); long d = getTime(1,2); } 在OnOk里面陷死,如果注释Oninit的代码,OnOK里面就可以过.所以我怀疑最大的原因还是没有足够的堆栈给mytest.dll.
pingglala 2014-09-04
  • 打赏
  • 举报
回复
引用 13 楼 micropentium6 的回复:
[quote=引用 12 楼 pingglala 的回复:] libtest.c:1: warning: -fPIC ignored for target (all code is position independent
interesting! I wonder if this is a default behavior of gcc for cygwin? as for ur question, I know windows and linux has some difference in terms of time handling. I bet cygwin/gcc messed it up...[/quote] 我刚网上搜了一下,有以下说明: #gcc -c -fPIC calc_mean.c -o calc_mean.o For some reason, gcc says: cc1: warning: -fPIC ignored for target (all code is position independent) It looks like -fPIC is not necessary on x86, but all manuals say, it's needed, so I use it too. 听他这么讲,有可能是32位系统编译才会出这个warning吧,我今天刚好就在下64位的cygwin.刚看到你昨晚的回复,所以马上就到原来32位的cygwin去试了. cygwin 64bit is downloading , 怕缺少什么库,所以选的东西有点多,有点大, I'm now waiting... btw,你说可能windows和linux在处理时间上有区别,那我先做别的例子来测试吧.但说回来,cygwin做的就是跨平台,应该都会顾及到时间处理的转换吧,这个我网上再确认下.
  • 打赏
  • 举报
回复
引用 12 楼 pingglala 的回复:
libtest.c:1: warning: -fPIC ignored for target (all code is position independent
interesting! I wonder if this is a default behavior of gcc for cygwin? as for ur question, I know windows and linux has some difference in terms of time handling. I bet cygwin/gcc messed it up...
pingglala 2014-09-04
  • 打赏
  • 举报
回复
引用 11 楼 micropentium6 的回复:
wait a minute,,, you don't have -fPIC flag for gcc? Position Independent Code means that the generated machine code doesn't depend on a specific address in order to work. This is mandate for compiling a shared library because of the nature of dynamic linking. for example: gcc -fPIC -g -c -Wall a.c gcc -fPIC -g -c -Wall b.c gcc -shared -Wl,-soname,libmystuff.so.1 -o libmystuff.so.1.0.1 a.o b.o -lc
我刚刚用你的方法重新编译了,但是没有效果,还是一样: # gcc -fPIC -g -c -Wall libtest.c libtest.c:1: warning: -fPIC ignored for target (all code is position independent ) # gcc -shared -o libtest.dll libtest.o
  • 打赏
  • 举报
回复
引用 10 楼 pingglala 的回复:
[quote=引用 1 楼 micropentium6 的回复:] what if you isolate the method having the function call defined in sys/time.h? will it crash as well?
今天又重新试了,竟然发现在简单加法运算的dll中加入<sys/time.h>头文件,也可以正常使用,将加法运算换成时间运算后,程序就变得崩溃。 下面那个是OK的: #include <stdio.h> #include <sys/time.h> int AddFunc(int a, int b) { return a+b; //struct timeval tv; //gettimeofday(&tv, NULL); //return (int)(tv.tv_sec*100+tv.tv_usec); } 下面那个是崩溃的: #include <stdio.h> #include <sys/time.h> int AddFunc(int a, int b) { //return a+b; struct timeval tv; gettimeofday(&tv, NULL); return (int)(tv.tv_sec*100+tv.tv_usec); } 另:崩溃那个dll,我用gcc编译成exe是可以正常跑的。 [/quote] wait a minute,,, you don't have -fPIC flag for gcc? Position Independent Code means that the generated machine code doesn't depend on a specific address in order to work. This is mandate for compiling a shared library because of the nature of dynamic linking. for example: gcc -fPIC -g -c -Wall a.c gcc -fPIC -g -c -Wall b.c gcc -shared -Wl,-soname,libmystuff.so.1 -o libmystuff.so.1.0.1 a.o b.o -lc
pingglala 2014-09-03
  • 打赏
  • 举报
回复
引用 5 楼 pingglala 的回复:
回复zhxianbin 我没用VS编译过C,现在代码是linux下的c程序,我想让它跨平台,同一份代码可以同时被windows和linux调用,现在是把它编译成dll给window调用。
代码是linux下的代码,不能用vs编译的,平台不一样,依赖的库不一样,要用VS编译成功的话,就要修改很多代码,我现在是要用同一份代码。
zhxianbin 2014-09-03
  • 打赏
  • 举报
回复
引用 5 楼 pingglala 的回复:
回复zhxianbin 我没用VS编译过C,现在代码是linux下的c程序,我想让它跨平台,同一份代码可以同时被windows和linux调用,现在是把它编译成dll给window调用。
跨平台也是要编译的,不知道与编译器是否有关,我觉得可以试试用 vs 编译成 dll
pingglala 2014-09-03
  • 打赏
  • 举报
回复
回复zhxianbin 我没用VS编译过C,现在代码是linux下的c程序,我想让它跨平台,同一份代码可以同时被windows和linux调用,现在是把它编译成dll给window调用。
pingglala 2014-09-03
  • 打赏
  • 举报
回复
to micropentium6: I have try that,I just added the “#include <sys/time.h>“ to the dll which works, then it crashed! So the <sys/time> can cause the problem, means class under linux can not work! Then how can I compile it successful?
pingglala 2014-09-03
  • 打赏
  • 举报
回复
dear micropentium6: 你是说只包含<sys/time.h>,实现里面不作time的功能处理吗?我也刚想到这个,想试一下。
zhxianbin 2014-09-03
  • 打赏
  • 举报
回复
VS 也可以把编译 C 的吧
加载更多回复(3)

18,829

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 专题技术讨论区
社区管理员
  • 专题技术讨论区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧