weixin_39834767
weixin_39834767
2021-01-11 21:16

实在看不下去了,所以才发这文,码主,你看看吧

主要是看不下去了,才写的, 有些太常识了,我扯这些常识,反而显示的我小孩子, 可能你也明白的,只是因为偷懒,才不去那样做, 并不是你菜, 为避免误会,吵架等,特意说明一下

  1. 你这是DLL的全部是默认的cdecl!!! ,在Windows中,标准规则是stdcall!!!!!!!,包括回调都是stdcall, 现在要去改cdecl, 别人的程序,必然报错, 你看看你的用户量,量小,能够保证通知到的,或是产生的问题不大的,那修正为stdcall, 具体酌情考虑吧 DWORD __stdcall GetTickCount(); DWORD __stdcall Sleep(dwMilliseconds:DWORD);

常见的有stdcall/pascal/fastcall/cdecl 这4种,总的来说是,API的参数寄存器存放顺序,从左到右,从右到左, 临时堆栈谁释放问题, stdcall是从右往左(目的是format(xxx,a,b.c...)可变长度时.. VC内部,或是默认 cdecll, 不加修饰符时,默认也是cdecll

给你找的,你可以看看 https://www.linuxidc.com/Linux/2010-04/25290.htm http://www.3scard.com/index.php?m=blog&f=view&id=10 ( 没有BS你的意思,纯好意, 你的代码中,没有注意到强制stdcall,可能这方便面意识淡薄,所以才强调一下)

  1. 这辈子第一次见到有人写dll,居然使用内部类做为回调参数的的 string是C++内置类型,实际上,也算是一个类(类实际在编译中,一般都处理成record/struct形式存放在编译后的bin中的) 不同的版本,不同的编译器(vc,bcb,或其它c++的编译器),对于这类非直接内存数据,都有自己的处理方式 除非是你强制要求用户和你使用同一版本的vc(如果微软对这个vc打个补丁涉及到string,那么甚至需要大家连补丁都一样),或是dll的和exe都由用户自己同一个编译器编译,或是直接把dll的代码包含在exe中,不使用dll了, 否则,内存中数据必然不一样, 不可能让exe正常调用这个dll,到时出现各种无理头问题,又找不到原因 修正方法, 全部改成 char * (可以考虑wchar,不过一般以char*为主)

作为一个dll,需要按Windows的标准规范,那么所有的编译器,都能很好的支持的 常见的delphi7/DelphiXE, VC, BorandC++,Java, gcc(MinGW/Cygwin)... 这个规范简单来说, A.stdcall (个别因效率原因,或是开发方便等原因,不按上面的来,也要书面写明) B. API交换数据时,要32bit对齐, 一些枚举,bool或其它,都要显式申明,防止不同编译参数影响到内存对齐 参数要尽可能是内存本质的,一般以 ansiChar为主, 个别可以是 WideChar,但大多数是* ansichar 这和utf8兼容,和gbk也兼容 WideChar,最多只有65535个字符,实际没这么多, 在处理新字码时,必然有损,所以widechar不应该使用 因为 windows当初设计时,9x年代,,想着65535总够了,现在utf8里一堆垃圾,说不定哪天4byte 都不一定够用,所以还是ansichar/utf8/gbk为主吧!!!,至少不会有错 C.所有枚举,需要强制指定开始点和结束点,即 enum_start=0, enum_MAX=0x7fffffff, 这样避免编译器,自作主张,一看没超过255,就用一个byte来存储,一个程序中没事,跨文件交换数据 就成问题了 D.所有结构,要强制指定对齐方式. 通常是4byte为单位对齐,

#pragma pack(4) //强制4byte对齐 struct { //DWORD dwsize 复杂数据,可考虑添加dwsize, 这样dll可以根据dwsize判断exe是哪个SDK版本开发的, // 同时也可以用于操作时的越界判断, windows大多数结构,都有这样的大小,值, char ver; char flag; char res1[2]; 这里少了2个,所以故意添加2个(也可用于将来扩展功能预留), 以防止编译器收缩,不使用时,一律填0, 将来要用时,知道0是不使用的,非0才是有效数据 char X; char Y; char X; char res2[1]; 结束时,防止编译器收缩,所以故意对齐 }

pragma pack() //恢复编译器默认对齐方式

这样故意添加res成员,占位置,一般情况下32位系统是正常了, 万一64bit编译器,将来编译器开发人员一时想不开,64bit默认8byte对齐, 或是编译器因为需要其它数据需要参数设成8byte对齐, 这时必然出错 所以最好再加上pragma pack 显式指定一下

这些大小值,全部设置后,由于结构成员很多,可能会弄错,比如,res[xx]算错了等 全部弄完后,需要printf("Name=%s, sizeof=%d",xxx sizeof(xxx));一下, 全部确认一一下

不过,总的来说,只需要修改h文件, 改动量并不大, 只是你的老用户,兼容性可能有问题 (他们需要拿了这个头文件,重新编译一下自己的程序,代码上,一行也不用改)

  1. 一些函数, 比如wkeGetUserAgent,返回是一个 ansichar的指针, 正常,应该是,让用户给定一个内存空间, dll负责填充数据, 通常还会是二次调用 第一次调用时,buff=null,*size返回大小 第二次根据size申请内存size,然后get(buff,size) 如果是字符串数据,防止意外,及兼容性,通常size+1多申请一个数据, (或是用户知道这个数据也就是4K长撑死了, 直接一次调用,给出4K内存, DLL调用后更新size,告有效长度 这样,用户也不用怀疑这个返回内存块要不要外部exe去释放的问题 不管什么语言,默认都是谁调用,谁申请内存(exe调API_Filldata(xxx),那么xxx由exe申请,也由exe去释放,)

但是,图方便,可以直接流氓式,返回 char的数据,大多数不会出问题,不过: char p=GetCurUrl; //返回www.xxx.com int Len=strlen(p); 用户一堆后续操作,可能浪费了很多时间,也可能是用户电脑太卡或其它原因,,同时web的的线程,js倒计后,指向 www.newurl.com CPU时间片,代码块间轮循时,不可能保证大家都是平等的,有的多轮到些,有的少些,多核下,优明显,进程卡时,优明显 用户再对p进行调用, 这时p的值已经变成newurl了,也可能被你释放了,也可能不安全了(结尾问题) for (int i=0... i<Len) { ..... } 为了解决这种问题,需要书面写明, 告诉用户,这个结果值是安全的,是常量的,是...的等等才行 但终归不是正常调用方式 用户无奈解决方法,要可能是 GetCurURL后, 马上newmem块内存,把结果拷进去, 以防止web核心对数据改动 但总归不如用户自己申请的方案 称妥

  1. WKE原作者,不知道是不是你,可能不是WKE原作者故意为子, GG的可能性更大一些 wke.dll中, 画屏,居然要用户自己实现,自己去申请bmp区域,自己去计算鼠标位置等, 超级变态,浪费内存,浪费IO, 这种做法,据我所知,只有andriod的api是显示结构这样的, 大多数用户,并不想这些, 只想像IE的Webbrower那样简单调用,因为IE的webbroiwer兼容性已经越来越不行了, 很多时候显示一个网页,会报js错误,或是报找不到项目之类的(但在标准IE中运行没这问题) 另外一些人,想实现一些高高高级功能,这时才会把画屏功能交用户,用户可有是要在exe中,嵌一块自主强超强的网页,甚至在游戏中,贴图方式显示个网页也说不定,这时才需要GetBmp,GetYUV之类的原始数据 你的wkeCreateWebWindow,比原版的WKE方便的多, 联想到原来WKE的不合理,所以才提这个

5.你的DLL导出了C++类, 一堆的??xxxxxxxx@!$#@!$@#$!导出名,实际并不安全,而且开发并不方便的 好的做法是模仿COM,导出一个进程COM接口(比如wmp.dll就是这样的) 比如定义一个 wkeCreateWebCore(); 返回接口 接口如下: Interface Ixxxxxxx; function setpos(L,T,W,H,isshow); function LoadUrl(url ) function .... .... (详细,你可以vc随便打开一个例子,或是用exescope打开c:\windows\system32\wmp.dll

用户在使用时,不需要创建任何类,只需要 web=wkeCreateWebCore(); web.setpos(...) web.loadurl(...) function regcallback(CB callback,void user); 这和标准的类代码,完全一样

不过com方式缺点时,有些地方让用户不清楚本质,比如指针的指针,最后这个内存要不要释放(比如DirecShow->mediatype.format数据),调用顺序等,有点糊, 所以, 在使用时,尽量按标准的,原始的数据类型, 可能有内存释放问题时,文字写明 在处理回调,事件类时,不要用COM的方式,而是标准的C/C++方式

不要使用进程以外的COM(比如开机时,开始菜单按钮卡着了,或是一些程序操作时,开始菜单卡了,IE卡了,操作一下,结果会是影响到资源管理器之类,.都是跨进程COM的,不建议这样搞)

太多了.不想说了, 不是一句话两句话说的清楚的,

该提问来源于开源项目:weolar/miniblink49

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

69条回答

  • weixin_39944638 weixin_39944638 3月前

    卧槽GitHub也有喷子。

    Welcome to the REAL world! Friend. 00091DEB

    点赞 评论 复制链接分享
  • weixin_39789646 weixin_39789646 3月前

    推荐duilib:https://github.com/duilib/duilib 而且duilib写界面也简单迅速,设计也很好,关键是体积非常小,1M多点的样子。

    点赞 评论 复制链接分享
  • weixin_39830012 weixin_39830012 3月前

    在神僧宝地打个广告“钉钉windows客户端大量招人“,有兴趣联系我。

    点赞 评论 复制链接分享
  • weixin_39899226 weixin_39899226 3月前

    在神僧宝地打个广告“钉钉windows客户端大量招人“,有兴趣联系我。

    呵呵,给我发邮件了,又说最近几个工作时间太短,没在小公司待过吗?

    点赞 评论 复制链接分享
  • weixin_39968722 weixin_39968722 3月前

    知乎观光团

    是也乎,( ̄▽ ̄)

    点赞 评论 复制链接分享
  • weixin_39770416 weixin_39770416 3月前

    知乎观光团~~ 楼主加油!哈哈哈

    点赞 评论 复制链接分享
  • weixin_39944638 weixin_39944638 3月前

    知乎观光团来迟了,话说第一次知道GitHub 上也能当成论坛撕。

    233, 讲道理前几天python的创始人不就因为撕累了辞职不干了么?

    点赞 评论 复制链接分享
  • weixin_39786617 weixin_39786617 3月前

    撕撕更健康~

    点赞 评论 复制链接分享
  • weixin_39904522 weixin_39904522 3月前

    "你们打拼音居多, 打五笔的,打字快,所以打的东西多,不过质量不高,打的多了,有时条件反射,打错了自己都没发现, 开发久了才有这个锅之类的" 可能是明朝就开始写代码的程序员,你们要体谅一下,不过能知道github也算挺与时俱进的了。

    点赞 评论 复制链接分享
  • weixin_39611008 weixin_39611008 3月前

    完全没耐心看下去了,楼主不少常识错误,半桶水不可怕,可怕的是还出来傲娇撒泼啊。 今天刚摸神僧的mb,看了一些文章,顶礼膜拜。 建议楼主应该到神僧手下实习,接受调教。 windows的调用约定,实为糟粕,M$到了x64不也苟了,还不是迎来了和GNU的大一统(除了thiscall依然异类)。

    点赞 评论 复制链接分享
  • weixin_39611008 weixin_39611008 3月前

    神僧无需和他置气,你的时间比我们更富价值,这等小事儿交给大家。

    点赞 评论 复制链接分享
  • weixin_39641450 weixin_39641450 3月前

    Talk is cheap, show me your code.

    点赞 评论 复制链接分享
  • weixin_39583013 weixin_39583013 3月前

    知乎观光团.

    你肯定是沒有看過自由門的repo

    点赞 评论 复制链接分享
  • weixin_39623716 weixin_39623716 3月前

    楼主的文字有点情绪化,作为一个开源项目不要要求太多;另外,各楼层盲目的跪舔也是有点过了,会不会让作者飘起来

    点赞 评论 复制链接分享
  • weixin_39964528 weixin_39964528 3月前

    阁下先分清 star 和 fork 的区别,再来指责别人盲目不盲目吧。

    点赞 评论 复制链接分享
  • weixin_39789857 weixin_39789857 3月前

    Mark and wait for your si bi.

    点赞 评论 复制链接分享
  • weixin_39611161 weixin_39611161 3月前

    老师傅放码过来🐎

    点赞 评论 复制链接分享
  • weixin_39531834 weixin_39531834 3月前

    居然有人喷linux,linux的显然更标准。

    点赞 评论 复制链接分享
  • weixin_39786534 weixin_39786534 3月前

    20年编程经验的0个star

    点赞 评论 复制链接分享
  • weixin_39996798 weixin_39996798 3月前

    卧槽GitHub也有喷子。

    点赞 评论 复制链接分享
  • weixin_39898733 weixin_39898733 3月前

    知乎观光团

    点赞 评论 复制链接分享
  • weixin_39944638 weixin_39944638 3月前

    没写过c/cpp,过来围观一下。

    点赞 评论 复制链接分享
  • weixin_39904268 weixin_39904268 3月前

    知乎观光团

    hahahahahaha, zhe ye neng si bi?????

    点赞 评论 复制链接分享
  • weixin_39621456 weixin_39621456 3月前

    我提个建议啊,关于dll的函数导出,最推崇的方式。大致这样 -- 整个dll就一个导出函数,叫做 void *getFunctionList(); 这个函数返回一个结构体的指针 --

    cpp
    struct FunctionList {
        int  (*getVersion)();
        void (*func1)(int a, int b);
        int  (*func2)(int a, int b, int c);
        char (*func3)(int a, int b);
        ...
    };
    

    结构体的第一个函数固定,返回版本号;其他函数以后随便改。 将结构体做成头文件,和dll一起发布。

    以后可以畅快的版本升级,头文件写好就行了。C/C++外其他语言想调用,你们自己想办法。 这是在做IAR编译器的某个驱动时看到的做法。

    异不异类?好用就行。

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    你这方式我想过,不过有几个问题所以没采用。 一个是如果接口变化了,就不兼容以前的老版本了。这个对用户来说特别不友好。像我这种每天换个版本的,用户需要不停的编译再发布。 二是无法在导出表里看到有哪些函数。很多时候还是需要知道某个出问题的用户的dll是不是采用了某个新接口导致。虽然可以通过查询版本号,但毕竟很麻烦。 综上,这种方式几乎没啥优点,简易性不如现在直接用c接口导出。

    点赞 评论 复制链接分享
  • weixin_39636333 weixin_39636333 3月前

    知乎观光团

    点赞 评论 复制链接分享
  • weixin_39849418 weixin_39849418 3月前

    歪个楼问一下楼上上的问题,接口变化如何保持兼容?感觉只要一变内存结构,就会导致不兼容,有什么办法可以做到兼容?

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前
     这种方式无法做到兼容,除非每次只在最后追加接口,不改原有接口。所以这也是我不采用的原因。其实这种方式就是COM嘛。
    
    点赞 评论 复制链接分享
  • weixin_39849418 weixin_39849418 3月前

    我也是想到了COM。 不过做兼容总是会需要新老接口全在导出列表上吧?只不过可以不需要强制末尾加?

    点赞 评论 复制链接分享
  • weixin_39621456 weixin_39621456 3月前

    这个方式不解决兼容问题,只是接口变化时比较好处理。 每一版的接口,都有固定的结构体描述,不容易搞错,更不会冲突。 实在要兼容,调用dll的人根据版本号做处理。

    点赞 评论 复制链接分享
  • weixin_39899226 weixin_39899226 3月前

    windows api一直是stdcall吗?还真没注意过,再说了别的语言不支持cdecl?秀自己的无知吗?用别人的东西,本来就要遵守别人的规则。

    点赞 评论 复制链接分享
  • weixin_39605647 weixin_39605647 3月前

    年龄高不代表技术如何,我司也有一个老大哥,四五十的人了,走不出自己的思维,于是一个月被开了

    点赞 评论 复制链接分享
  • weixin_39816062 weixin_39816062 3月前

    知乎观光团来迟了,话说第一次知道GitHub 上也能当成论坛撕。

    点赞 评论 复制链接分享
  • weixin_39837124 weixin_39837124 3月前

    教授就是教授啊, 太能扯了, 搞软件的 你 去搞硬件都这么牛, 这在儿闹腾啥呢?! 还扯输入法 神经反射了,牛人

    点赞 评论 复制链接分享
  • weixin_39837124 weixin_39837124 3月前

    爱用不用啊, 有问题 提 issue 不就行了吗????

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    另外微软MSDN清楚的说明了,stdcall不支持不定参数。不知道你搞了20年,连stdcall不支持可变参都不知道是什么情况。如果你说你手动嵌入汇编在stdcall里清理堆栈,那我真是无话可说。

    点赞 评论 复制链接分享
  • weixin_39944375 weixin_39944375 3月前

    看完日报来围观

    点赞 评论 复制链接分享
  • weixin_39964528 weixin_39964528 3月前

    x64 全是 fastcall,包括所有 DLL,M$ 自己都不要了还有人舔?我们只用 C++,只从头文件用,有什么不行的?你要 stdcall 要 COM 自己封装去,大可以给完整 Chromium 贡献去,我们只要一个开箱即用的东西。

    点赞 评论 复制链接分享
  • weixin_39589766 weixin_39589766 3月前

    https://guides.github.com/features/mastering-markdown/

    点赞 评论 复制链接分享
  • weixin_39642761 weixin_39642761 3月前

    咦,这位也是D7时代穿越过来的人嘛……我记得那时候大家火气没那么大的呀

    点赞 评论 复制链接分享
  • weixin_39866419 weixin_39866419 3月前

    楼主太年轻,碰到这样的大牛,直接一句"您说的对"

    点赞 评论 复制链接分享
  • weixin_39996739 weixin_39996739 3月前

    只能证明你工作经验不足,接的活非常少

    一个底层劳动力还把自己给感动了

    点赞 评论 复制链接分享
  • weixin_39616287 weixin_39616287 3月前

    C++
    typedef struct {
    wkeProxyType type;
    char hostname[100];
    unsigned short port; //这里方要加2个byte手工对齐,防止被编译器欺负
    char username[50];
    char password[50];
    } wkeProxy;
    
    `

    这怕不是还要写packed 2333

    点赞 评论 复制链接分享
  • weixin_39746229 weixin_39746229 3月前

    行家啊。 Don't BB, show your code

    点赞 评论 复制链接分享
  • weixin_39530149 weixin_39530149 3月前

    Re:

    Linux通常没有多用户合作,前后兼容等意思, 因为Linux程序各自为政,不考虑前后兼容问题,Linux也没有操作友好度,操作安全意识 ,什么都是文件, 资源也拼命使用,所以通常做的东西比较单板,好在人多,大家把某个exe模块拼成一个功能,像IOS,那样,限制一下,不能这么操作不能那么操作,单一性的功能,可以使用了

    某些人用了20年电脑,难道对 Linux 一点都不了解么? 对 Unix 世界的文化、编程哲学一无所知么? 在知乎上面实在是看不下去了。

    点赞 评论 复制链接分享
  • weixin_39861498 weixin_39861498 3月前

    Linux通常没有多用户合作,前后兼容等意思, 因为Linux程序各自为政,不考虑前后兼容问题,Linux也没有操作友好度,操作安全意识 ,什么都是文件, 资源也拼命使用,所以通常做的东西比较单板,好在人多,大家把某个exe模块拼成一个功能,像IOS,那样,限制一下,不能这么操作不能那么操作,单一性的功能,可以使用了

    Linux的世界是对geek友好的,而Windows是对最终用户友好的。两者互不相容。

    作为一个Linux的程序员,他是不怎么需要管其他“用户”的用户体验的,这里的“用户”也包括了自己的SDK的使用者——他们认为,我的所有特性,所有命令,所有版本变更,都是你需要学习的东西,如果你学不会,说明你不是我的用户。

    而作为一个Windows程序员,如果他只会写命令行程序,这程序还需要复杂的辅助依赖、管道组合才能用,那他基本上就是自绝于大部分最终用户的。我们可以看到很多Windows程序员的Windows编程之旅都是从窗口界面开始的。

    那么在Windows下写SDK的程序员,又应该遵循什么样的设计哲学呢?

    我觉得应该还是要属于Windows的,尽可能多地考虑用户体验、兼容性等的思路。调用约定不是什么大事,但是暴露给外部的接口,在可以使用常用类型(const char)的情况下,使用自定义类型(等同于void)我觉得还是不大好的。

    点赞 评论 复制链接分享
  • weixin_39609718 weixin_39609718 3月前

    亲你你互联网上的人儿么,锅这个梗你都不知道么?

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    你在搞笑吧,到底谁在无理取闹。我哪句话说什么子库用这种,就必须用这种? 我明确写着,讨论curl那种是为了证明cdecl的库也很常见,别人用的好好的,我怎么就不能用了? 我每句话都是回复你的问题,你写了几千字,扯些乱七八糟的,还说我东拉西扯?你工作了20几年,都是在写低端代码吧,硬磕cdecl的人是你,我早说明了,用哪个方式都可以,调用者按照声明去用就行了。 你自己看看你第一个回复,好像我用cdecl是多么罪恶似得,这不是在搞笑吗?windows上用cdecl的多了去了,你少见多怪而已

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    你自己看看新建一个vs工程,默认是不是cdecl?

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    qq 20180717223315

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    自己看下吧,微软是怎么说明的。这里也解释了我说的会多几个字节的问题。不知道你有什么好坚持的。好好按照微软的说明做吧

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    “你这是DLL的全部是默认的cdecl!!! ,在Windows中,标准规则是stdcall!!!!!!!,包括回调都是stdcall, 现在要去改cdecl, 别人的程序,必然报错, 你看看你的用户量,量小,能够保证通知到的,或是产生的问题不大的,那修正为stdcall, 具体酌情考虑吧” —————— 我又不是windows api,为什么要非要改成stdcall?哪里有什么标准规则?微软自己都说了c++默认是cdecl。我只是用了vs默认推荐的调用方式而已。 而且谁会报错?只有不看调用方式就瞎调用的人才会报错。

    点赞 评论 复制链接分享
  • weixin_39609718 weixin_39609718 3月前

    说句不好听的话,作为一个开源库,有强迫你使用么?有收了你一分钱么?既然你是20年的老码农,经验技术又这么牛逼,你大可以自己撸一个啊,别说用stdcall,用开了花都可以!既然要用mb,你就得遵守mb的规则,就像你用win一样,你就得遵守win的规则!20年!先做人在做事,别说你做20年,做到死估计也就这个样了!

    点赞 评论 复制链接分享
  • weixin_39616056 weixin_39616056 3月前

    哎呀,乖啦,
    download

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    1,stdcall什么时候是标准了?是什么的标准?微软用stdcall就是标准?微软有文档规定所有在他机器上跑的dll都必须的stdcall?我的wke.h显式写了#define WKE_CALL_TYPE cdecl,所有导出函数都是cdecl,有问题? 2,HWND在微软的实现里就是typedef struct HWND *HWND;至于你在外部使用就可以当成DWORD。我导出的wkeString也是一模一样的用法。 3,字节对齐这个我下个版本会写清楚。 4,??XXX??Xx这种是给我自己用的。而且那玩意都是v8的东西,其实是给调用nodejs的人用的。当然只能用这种形式。你要喷,就喷nodejs吧。 5,你说有报错,那就检查下调用方式、调用参数是否正确。如果都没问题可以反馈bug给我。但我相信这么简单的调用不会是mb的问题。

    点赞 评论 复制链接分享
  • weixin_39616056 weixin_39616056 3月前

    哎呀,乖啦,扫地,
    cute

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    好吧,大家心平气和点。目前你说的有两个问题确实mb的文档和头文件没写清楚。一个是没写明字节对齐方式,而是枚举的字节大小。下个版本加上显式申明

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    除了字节对齐和枚举的问题,其他的喷点一概不接受

    点赞 评论 复制链接分享
  • weixin_39581719 weixin_39581719 3月前

    不要乱喷,还摸电脑20年,这都搞不定还好意思说出来。 无条件支持神僧。

    点赞 评论 复制链接分享
  • weixin_39834767 weixin_39834767 3月前

    reopen后回复前面几个人

    我上面的内容里,可能不知不觉中有喷的意思,但是含量非常非常非常非常的少的, 主要是发现作者没有遵守 还担心误会, 故意加了一句, 不要吵架

    一些DLL的江湖规矩,不规范,所以来发表一下, 目的是希望作者下次注意, 现在已经不能改,但是显写定义一下,或是文档说明一下, 维护一个代码,工作量实际很大, 我并没有怪作者,包括偷懒,或是经验不足,弄错,或是其它,都没有怪的意思

    可是,作者自尊心爆棚, 反过来欺负人

    摸电脑20年,这和搞定搞不定无关,只是说经验很多,五味杂陈,人老话多, 或是不者说不太会犯新手的错误,互相考虑问题可以了眼于简单但冷门问题上,或是深层可能性上 DLL目的是 1.多程序共享时,在内存中只有一块,省内存.多个进程共享时,内核只有一块,只是映射一下 2.模块化,多用户独立分工开发,可以不关是别人怎么实现,只做自己的事 做成 DLL后,调用者不需要了解内部情况,并且随便折腾都行,不知道DLL内部某个东西内存真实地址,DLL提供的所有数值,随便折腾都不会破坏DLL空间,代码安全,

    如果花N多时间去折腾才把dll调起来,那失去了用成品模块的意义了, 一些莫名其妙的错误,可能就是定义不标准,在跨用户/语种/环境时出错,这些莫名其秒的错误,可能几天也不一定找的到原因, 还有一些Linux/Windows/固件不同开发者,对于架构的不理解, 照成问题

    硬件开发,通常没有多线程概念,更没有数据安全意识,在他眼中,所有代码都是顺序执行的,所有变量,内存地址都没有共享冲突概念的

    Linux通常没有多用户合作,前后兼容等意思, 因为Linux程序各自为政,不考虑前后兼容问题,Linux也没有操作友好度,操作安全意识 ,什么都是文件, 资源也拼命使用,所以通常做的东西比较单板,好在人多,大家把某个exe模块拼成一个功能,像IOS,那样,限制一下,不能这么操作不能那么操作,单一性的功能,可以使用了

    Windows,问题也很严重, 不过一下子不好举例

    挑这些剌,不要喷我怎么不去做一个系统, 做个系统是简单的,但是你根本不可能去运营的 驱动程序,必须开发,但厂家都倒毕了,文档也找不到了(比如 PS2键盘接口,IBM推出的,但是连个标准文档都没,大家都是看示波器,分析出信号格式,然后去写固件的) Windows右键菜单, 专利现在还没到期(好像还有半年), Apple当年和微次打了一架,没淡拢, Apple多年来,一直是单键鼠标,还吹说单键的好处, 后来卖iphone赚到钱了,专利也快到期了,才和微软互换了专利(好像还交了钱)现在的ocx里,才渐渐有了很多右键菜单

    一些话比较啰嗦,也是怕很多人不明白,所以才故意多写的, 现在很多新人,大多会web,py,java等,低层原理的都没概念,也不愿意去学 ("很多新人", 并不一定说是楼上几位, 不要对号入除,然后乱喷)

    stdcall, 我记的微信在9x年代时,官方出的书或是文里,是做为推荐方式的, 这不能说是绝对是标准,但是这么多年下来,大家都是按这个方式去做dll的,不管是不是,都是显式写明的,保护任何情况下都不出错,保证向前前后兼容,早就不成文的标准/规矩了

    具体你可以搜索,所有像样的公司提供的SDK包,比如海康,大华,这些硬件厂家的SDK,所有微软的H文件,所有的跨语种Windows工具等 原本是Linux下的代码移值的除外,像opencv,ffmpeg,x264.faac等,就比较乱了,具体由编译工具默认值决定, 甚至opencv因为从api上,完全看不出retrun值是个什么东西,要不要去释放之类(返回值在实际可能是个内存块,但返回值,给用户的h文件中,被定义成int了,而不是void *), ffmpeg,不定时,结构体都有乱序改动(定义ab成员,后来想增加了,随手插上一个,变成acb),就算同是C开发,直接引用,也不能通过拷DLL/so方式来升级模块/功能

    说HWND是DWORD,因为对于外部用户来说,他就是个DWORD,不需要释放,用户以标准int32方式取值赋值,,不用关心内部怎么实现,类似 作者wkeCreateWebView返回的void *, 写成DWORD/Handle也没关系,反正用户不可能操作这个数据的,用户知道"Create"这词的 ,那肯定是要手工去释放的就行, 外部用户在重新定义API时,可以指鹿为马,只要保证API在交换数据时里内容和方式一样就行

    补一下 wkeLoadURL 这个,好像没有自动补http://的功能吧, 需要提供完整地址,才可以 可考虑判断一下,有没有 '://'字符串,确实要不要补头, 如果说错,当我没说

    重申,跨语种时,发现莫名其妙问题,很可能是作者经验不足,一些地方不按行例定义,产生的问题 所以,我不打算使用, 只不过这贴子,开了头,所以才有这个回复, 这是最后一次回复了.,请作者也把这个关了,大家都不要回复了,删贴也随你 还是删了吧, 很多内容扯的太远

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    1,微软用stdcall的原因是因为在那个年代,内存硬盘资源非常珍贵,stdcal可以让dll省几个字节。但现在早就不在乎这几个字节了,而且微软也绝对不会说stdcall才是标准。我用cdecl是考虑到这个可以支持不定参数,而且是纯C接口用的比较多的调用方式。现在开源库curl,libuv之类的,全都是cdecl。并没什么所谓的行规要用stdcall。 2,你说的我导出内部类,这个完全没道理。我导出的wkeString对外部调用者来说只是个DWORD而已,和HWND之类没任何区别。微软也是直接把user32.dll内部的struct __HWND导出来。 3,从你提的几个建议来看,你既没有认真看我的头文件也没认真看文档。否则就不会说出我没明确申明cdecl这种话来。 4,目前miniblink都已经商用了,delphi的封装也有很多人用。莫名其妙的问题很大可能是你没按文档封装而已,不要怪在miniblink头上。我研究windows内核和win泄漏代码的时间不比你少。大家心平气和的提意见就行了。你说的对的地方我自然会采纳。

    点赞 评论 复制链接分享
  • weixin_39834767 weixin_39834767 3月前

    没认真看头文件? 我都翻译你头文件到Delphi(pascal语言)了 ,还说没认真看?, 没看完到是真的,内容太多,有些项并不一定需要,优先翻译重要的的,先跑起来,后面需要哪个加哪个

    curl,libuv,这些原本是linux下的,移值出来的, 并不是windows开发者写的, 他不使用stdcall是否gcc能省几个字节我不知道,但怎么可以用于判定cdecl好,所以在windows中也用这种呢!!! 而且linux的行规原因,我是win为主的开发,如果我写个linux模块,我也会按linux方式去走,不会去考虑win的stdcall, 除非我打算写成跨平台模块,为了以后省事,提前写成stdcall,因为win下环境复杂,linxu下相对单一,都是gcc就算不是gcc的编译器,大家都去按gcc方式走(比如freepascal编译器算是另类,不像objC那样集成在gcc中,但是也编译成obj文件,再连接成elf,从模块接口,调试方式(gdb),全部按gcc方式走) Go编译器,单独编译器,也跨平台的,但原生也是linux开发的,作者也是linux开发者等等.所以除非指定,否则也是按linux方式调用

    windows是stdcall,一般二次开发包都是stdcall, 这已经是惯例,那么尽管优点很少,甚至有点缺点,为了兼容性,习惯性,应该考虑stdcall stdcall和cdecel都是从右到左的,所以都支持不定长参数!!!!!, 区别是干完活了,谁打扫战场

    fastcall是放参数放在寄存器中, 超频繁调用的函数,可以加快速度,循环类,加密类等 pascal/fastcall,是从左往右存放参数,所以不支持不定长函数

    无参数api stdcall/pascal写反了 ,正常使用, 有参数的,写错了,有时数据错乱,有时参数顺序反过来,fun(a,b)变成fun(b,a),肯定不能正常执行,而且返回时,通常报错 stdcall/cdcel写反了, api功能正常执行,但返回时,不一定马上报错,多调几次后,肯定报错,或是后面连续几行代码里报无理头错误(连续几行的意思是只在附近行报错,不在其它异步线程中,或是很远的地方报错)

    不清楚你说的省几个字节的问题,可能理解差异,或是表达上差异, 但居握我所知, 汇编代码层面上, 这stdcall/cdcell,两者 99%是一样的,不方便贴个OllyDbg图,所以专门给你找了个url,有汇编代码 https://blog.csdn.net/jqsad/article/details/51670826

    有些话,不清楚是你用词不当,还是不懂, 比如纯C接口比较多的调用方式, 纯C接口调用的多, 感觉多少有点 纯C所以才cdcel的意思在内, 同一个程序,内部如何调用可以编译器,编译参数,强行指定等决定 同个编译器,默认情况下相同调用方式, 偷懒,少打字,所以连显式定义也省了,这话才说的过去 我对这有异意, 你回复一句,懒的写文档,,懒的显示指定, 才比较让人接受+认可

    不清楚你所谓的商业应用, 这个根本拿不到台面上来说的, 本身是开源的,国内偷用开源的去卖钱,注册专利等多了(联想把 cat /proc/cpuinfo, 查看系统信息,都注册成专利了,脸皮厚的可以 大约七八年前看到) 而小应用,小单位使用你的代码, 那就算给你钱了,哪怕是给你个几百几千万,但用户量不多,拿这来说商用,有点自抬身份,不够谦虚吧的感觉吧

    我的代码: 一个空窗体一下, 放个按钮,按钮点击事件下,下面的代码 wkeInitialize; 初始化 obj=wkeCreateWebWindow(2,pnl1.Handle,0,0,pnl1.Width,pnl1.Height); //创建个对象 // 这里2改成0弹出窗口,但改成1, 会在一个不着边际的地方显示个没边框的webFrame // 我需要的2的应用,在一个窗口一个区域里显示个Web控件 // 一些回调设置, 全部取消,和加上, 没区别,要报错的还是报错 所以省略, // wkeResize(obj,pnl1.Width,pnl1.Height); 调整大小 wkeShowWindow(obj,True); 显示 wkeSetUserAgent(obj, '......'); 设置代理字符串,设不设没区别

    再放几个按钮,分别是下面的一行代码 wkeLoadURL(obj, 'http://abc.com/phpinfo.php'); 显示正常不报错, 鼠标可以在web区拖动选择块等 wkeLoadURL(obj, 'http://abc.com/index.html'); 显示正常不报错 ... wkeLoadURL(obj, 'https://github.com/weolar/miniblink49/'); 显示正常不报错 ... wkeLoadURL(obj, 'https://abc,com/a.jpg'); 显示正常不报错.....

    wkeLoadURL(obj, 'http://www.163.com/'); 报除zero错误 wkeLoadURL(obj, 'http://www.baidu.com/'); 报除zero错误 只要报错后, web区,绘屏死掉了,后面再也不会更新,比如调用loadurl(http://abc.com/index.html'); 不会再更新

    ------------------除上以上代码外,还有头文件翻译外,没有其它了多余的代码了------------ 文件使用miniblink-180716.rar中node_v8_4_8.dll或是node.dll. 单独绿色型一个dll, 和exe文件 (即总共2个文件)或是连同压缩包中resources/plugins/front_end目录丢进去 同样,没区别

    支持rar中的wkexe.exe却能正常显示163,baidu

    在http://www.163.com时,回调顺序

    wkeNavigationCallback http://www.163.com/
    wkeNavigationCallback http://3g.163.com/ wkeURLChangedCallback https://3g.163.com/touch/
    到这里,后面再也没有回调,开发环境中,侦测到除0错误,单独运行不报错,但web区停留在上次成功的页面上,再也不会更新了, 重复访问163.com 除了回调一次wkeNavigationCallback http://www.163.com/外,不会再有新动作

    因为上面几个api,太过简单, 原定义stdcall出错,全改成cdecl后, 其它就算是新手也不太可能翻译错头文件 或是写错代码等, 但我跑不正常, 还以为,有些看上去可选函数一定要调用, 所以按照wkeBrowser.cpp大部分都抄了个遍, 但要报错的还是报错 最后,只好到这里发贴,然后放弃

    关于字节对齐的 typedef struct { wkeProxyType type; char hostname[100]; unsigned short port; 这里方要加2个byte手工对齐,防止被编译器欺负 char username[50]; char password[50]; } wkeProxy;

    另外100,50这样的值不好,会照成非int32对齐, 这样影响执行效率,编译器不得已只好拆成解成32bit+int16+int8 这样的零碎指令

    而且50,100这样大小计算上不好内存错位,其它人想翻译代码,或是只想copy半个结构体(比如上只想拷proxtype+hostname这部分数据)

    应该是写成hostname[128], username[64]之类

    总之,习惯不好,以后要改掉, 现在这代码已经成型,不方便改了, sizeof(wkeProxy)一下看看 默认被压缩了,就加一下pack(1)/pack(2) 没压缩,赶紧插个char Res[2]上去

    你DLL参数是enum的, 应该定义成int的, gcc不清楚, windows上的编译器,默认会int32对齐的 参数是1-4byte的类型,都会强制成4byte,目的是效率,防止xx个参数,前面一个byte,后面拆解成(xx-1)*N倍的指令量, 但是编译器手贱去设定了参数不对齐,就惨了

    你不要再回复我了,不然我忍不住又来回贴

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    1,是你自己说“个别因效率原因,或是开发方便等原因,不按上面的来,也要书面写明”。我里面清清楚楚写明了是cdecl!你自己说你到底翻译了半天有没看到我申明所有调用都是cdecl?? 2,再次重申根本没什么行规要用stdcall!!用什么协议是库开发者自己的事情,使用者按照约定调用就完事了。 我说的几个开源库都是cdecl,是不是linux移植的有什么关系?你需要管这个库是哪里移植的吗?这几个库都是安装量过亿的东西,有出什么问题吗?是什么约定就遵守约定,这么简单的事情说这么多。 我举这些例子不是说cdecl有多好,是想说用cdecl的成功案例也有很多! 我用cdecl到底有什么兼容性??我需要兼容谁了?那些不按规定就调用的,才是有兼容问题

    点赞 评论 复制链接分享
  • weixin_39609718 weixin_39609718 3月前

    感觉是在win开发久了的锅吧,类unix系统下有这些问题么?,实在觉得这样不行可以自己改呀,mit又没限制你修改的自由.

    点赞 评论 复制链接分享
  • weixin_39609718 weixin_39609718 3月前

    有这牛逼码字的精神,还不如去码代码?,手底下才见真招

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    还没写完吗,等了好久了

    点赞 评论 复制链接分享
  • weixin_39824191 weixin_39824191 3月前

    典型的不懂装懂。学了半瓶子c++就出来晃了 1,用cdecl还是stdcall是我自己的事情。调用者声明跟着一样申明就行了。出错的全是不看头文件的人。我又不是微软的官方dll,你管我用什么?世界上这么多大型开源项目,尤其是纯C的,基本都是cdecl,例如curl。 2,说什么用内部类,说明一你没看mb代码,二你代码写的少。我导出的wkeString只是个指针,需要操作则只能调用提供的wkeGetString之类的api。你管我导出什么内部类?你看看微软的头文件里,HWND是不是也你说的内部类? 3,结构体对齐这个,按照vs的默认设置就行了。别的编译器设置成vs默认对齐方式。这点下次我在文档里申明下。又不是什么错误,你激动什么? 4,这年头,还有人用两次申明内存的方式传数据我也是醉了。这是最傻逼的设计。别人只是需要几个字符串而已,你还要搞个这么复杂的获取方式。假如需要获取2个字符串,就要new四次,还要2个循环,麻烦的不行。现在mb返回的字符串如果是const char*,表示下一帧回收。不需要你回收,你也不能保存成持久化字符串,也不存在什么用到一半内容被改。这点看源码就知道了。当然,也怪我文档没写,等下我加上。 5,导出C++类, 一堆的??xxxxxxxx@!$#@!$@#$!。这些我让你用了吗?我文档和头文件里完全没提这些类,这是给我的electron模式内部用的。你管我导出什么?我有让别人调用吗 6,“wke.dll中, 画屏,居然要用户自己实现,自己去申请bmp区域,自己去计算鼠标位置等, 超级变态,浪费内存,浪费IO,”,这个叫离屏渲染,是给需要画在游戏等地方(例如D3D需要bitmap)。虽然繁琐,但能控制的更详细。如果不需要,就用简单的wkeCreateWebWindow。两种方式都有用途,不存在对错的问题。你在激动什么? 7,你居然还要我导出com。这都什么年代了,谁还想用这么繁琐的导出方式。现在统一成纯C接口,有问题吗?

    点赞 评论 复制链接分享
  • weixin_39616056 weixin_39616056 3月前

    楼主的文字,写的太情绪化了,而且幼稚,而且情绪化,我反正是没耐心看完,太喜欢碎碎念了,又臭又长。。。 扫地,这些 issue 你就把它们直接 close 了吧 :sunny:

    点赞 评论 复制链接分享
  • weixin_39834767 weixin_39834767 3月前

    说别人不懂装懂, 我摸电脑都20年了, 本想用一下,发现越来越乱,花了几小时翻译了你的头文件,最后调用,还报错,恨的牙痒痒的,所以才有这文 (我用Delphi7)

    1. 用cdecl还是stdcll本理是你的事, 便你这个放在github上,目的是让大家用的, 自然是要按标准的 就算你喜欢cdcell,那你至少显式写一句吧, 一般二次开发文档,SDK等,都是stdcall的 因为标准是stdcall, 我遇到过一些,刚开始用cdcel,后来偷偷改成stdcall的情况所以才提的

    2. HWND什么时候是类? 明明是个DWORD, wkestring是你内部的,还让用户调wkeGetString,这不是麻烦吗, 反正用户注册了回调,必然是要使用这个数据的,还让用户多调一次wkeGetString

    3.结体体对齐,大家都知道按默认设置,但是你确认用户肯定是VS用户?,用户的程序肯定纯Web应用?复杂应用,通常定义会很乱的,还是显式指定的好 对于自己的dll/exe 这种肯定不能说错,但是跨用户,跨语种,绝对是个错

    4.显式调用, 这是在不清楚内存大小的情况下(复杂应用,结体体很乱时,数据可能超大,可能超小时) 但一般应用,大家清楚时,直接申请个足够内存就是了, 这样模块内部的内存区域,不会暴露给外部 假设void *v =GetData(); 代码多了,用户不注意,去对v写操作了, 就死翘翘了(const只是告诉编译器编译时检查语法,而不是真的只读) 你自己回收,但用户并不清楚的, 多线程环境下,是不安全的

    5.??XXX??Xx的, 一般开发人员不会去直接写的, 特殊跨语种时会使用(我不用), 我只是说这种不是很好,应该避免, 你的用户应该不会是用gcc之类的极端情况, 所以不用考虑

    1. 你干嘛老说激动, 这种渲染 虽然简单的解决了很多问题,但太费IO, 我只是说原wke的方式,不是很好 大多数人不用, 对你有wkeCreateWebWindow表示认可, 表扬你,你还要说我坏?

    2. 导出com,只是导出类的一种偷懒方式, 我是不太喜欢com的,只是想到那么乱,给你一个想法而以

    另外,我 wkeInit; wkeCreateWebWindow; wkeResize; (...一些注册,可有可无,都一样) wkeLoadURL(htttp://aaa.com/phpinfo.php) wkeLoadURL('http://github.com/weolar/miniblink49'); 静态简单的页面,都OK 但是 wkeLoadURL('www.163.com') 报除0错误 "floating point division by zero" 怀疑是弹窗原因,去注册他弹窗回调,但没有回调, 所以这个原因排除

    为是什么原因?

    算了,不想说了, 你说我典型不懂装懂, 经验积累超级多,自然会超级乱,方方面面都要说到,但太多了,又会给人感觉说不清楚

    那我说你,典型的小孩子, 刚出来混,没经验,只不过,年经人精力不错,所以才会去鼓捣个代码放github之类 (后面半句,语义 中性,)

    不想说了.88 close

    点赞 评论 复制链接分享