太监的原因:

    时隔两年,VC与JavaScript交互系列的最后一篇关于JavaScript如何调用c++的文章终于出炉了。为什么会隔了那么久?因为本来打算太监的,可是看到热情的网友们的眼神,从期望变成了失望,在我的心里激起了层层波澜。两年后的今天,还是坚持把它写了出来。其实当时刚写完VC与JavaScript交互(二)的时候,参考网上的资料,已经把JavaScript调用c++实现了。可是实现方法太恶心了,代码写出来太复杂太麻烦了,而且还涉及到了一大堆见都没见过的COM接口,每个接口都是一大堆函数和一大堆参数,虽然实现代码写出来了,但是为什么这么写,根本讲不清楚,怕误人子弟,便可耻的太监了。

    当初为了写自动打开网页,自动填单,自动提交的小程序,看了一下这方面的东西,由于当时只涉及到了VC调用JavaScript,没有涉及到JavaScript调用VC,所以也没有花时间去深入了。这两年期间,好几次想把 VC与JavaScript交互(三)写出来,可是发现这个东西实在是太麻烦,太复杂,看不透,剪不断,理还乱,抽刀断水水更流,举杯消愁愁更愁。代码写出来以后我总是怀疑是不是搞错了,感觉是不是走了弯路,直到今天我仍然怀疑是不是有更好更简单的办法来实现JS调用C++。为什么说它非常麻烦和复杂,可以看这里http://dgj0600.blog.163.com/blog/static/440604322012102325015495/
这是网上找到的一段JS调用C++的代码,密密麻麻的,根本不知道该怎么把它解释清楚。

    实际上关于VC与JavaScript交互,最熟悉它的人应该是开发Activex控件及IE的BHO插件的程序员,他们一定能讲清楚其中的原理,讲清楚每一个API和接口的用法。不过搞这些的人越来越少了,现在WEB上的Activex控件也是越来越少了,关于ATL的书都在10年前就绝版了,可想而知现在还有多少人研究这个东西。

吐槽WebBrowser:

    WebBrowser这个东西真是让人爱又让人恶心,刚开始使用觉得挺简单的,导航、刷新、前进、后退、获取其中的HTML,都还比较易用,很快就爱上了它。但稍微深入后便发现了这种闭源软件的弊端,难以扩展和改造!比如要用WebBrowser开发一个多进程浏览器,如何在进程间共享Cookie。比如要针对不用的URL设置不同的HTTP代理来访问。比如要让它支持需要用户名密码验证的HTTP/SOCKS5代理等。WebBrowser根本没有提供这种接口来实现这些功能,只能是通过APIHook等办法来实现,既麻烦又不稳定可靠。而且WebBrowser这个东西还非常慢,本来IE就已经够慢了,WebBrowser作为IE的简化版,当它嵌入到我们的程序中时,WebBrowser中的HTML排版、渲染引擎、JavaScript解释器居然都是运行在我们程序的主线程(UI线程)中!所以你可以发现,如果WebBrowser加载一个内容非常多,非常复杂的页面时,在加载期间,你的程序就像假死了一样,同样如果HTML页面上的JavaScript代码在进行繁杂的运算时,你的程序界面又假死了。因为你的UI线程在运行JS解释器,你的UI线程在解释JavaScript代码并执行,在那期间它抽不出来空来去处理Windows消息循环,便假死了。

点赞CEF:

 在此强烈推荐CEF(Chromium Embedded Framework),即Chromium版的WebBrowser。Chromium就不用说了,它的快是非常出名的,即便作为控件来使用,CEF也运用了多进程技术,HTML的渲染和JavaScript的解释执行都是在格外的进程中,不会影响你的UI线程,奔溃了也不会破坏你的进程。而且CEF是用C++写的,对外提供的原生接口就是C++接口,比起WebBrowser的那套COM接口来说不知道好用多少倍。

JavaScript调用C++的一个相对简单的实现:

简述:
    上一章说到,一个JavaScript对象传到了C++这边以后,就变成了一个IDispatch*,然后我们用CComDispatchDriver接管这个IDispatch*后,就可以调用这个JavaScript对象的方法,获取这个JavaScript对象的属性,实际上CComDispatchDriver就是对IDispatch的包装,最终都是调用IDispatch::Invoke。同理,如果我们在C++这边构造出一个IDispatch*并传递给JavaScript,那么JavaScript就可以把这个IDispatch*当做一个JavaScript对象来使用,自然它就可以调用这个对象的方法,修改这个对象的属性,最终就可以实现调用C++函数,修改C++对象的成员变量,实际上JavaScript调用C++也是通过IDispatch::Invoke来调用。那么如何构造这个IDispatch就是问题的关键点。

实现:
    直接上代码,首先我建的是一个MFC对话框项目,WebBrowser已经拖上去了,添加为成员变量m_webbrowser。然后修改MFC为我们生成的对话框类CxxDlg(我的项目名为JsCallCpp,所以我的示例代码中就是CJsCallCppDlg):
class CJsCallCppDlg : public CDialogEx, public IDispatch
{
...
}
    将其多重继承于IDispatch。啊!多重继承?怎么把这种坑爹的东西搞出来?NO NO NO,不要谈多重继承就色变,这里的IDispatch里面的所有成员函数都是纯虚函数,本质上IDispatch就是个接口,C++的实现接口的方式就是多重继承,虽然不鼓励用多重继承来继承实现代码,但是像这样用来实现接口是面向对象中非常常用的。当然你也可以class MyIDispatch: public IDispatch,然后把MyIDispatch实例化成一个对象后传递给JavaScript来调用。这里之所以用CxxDlg来实现IDispatch,是为了方便,因为待会儿,我只要把CxxDlg的this指针传递给JavaScript,它就可以调用我的CxxDlg从IDispatch处继承来的虚函数Invoke,也就是说JavaScript就可以直接调用CxxDlg::Invoke,然后在CxxDlg::Invoke中可以很方便的调用我CxxDlg的其它成员函数。

 然后我写下了如下的HTML文件:

<html>
<head><meta charset="utf-8" /><title></title><script language="javascript">function ShowMessageBox(){if (cpp_object != null)cpp_object.ShowMessageBox("你好,我是Javascript,你是谁?");}function GetProcessID(){if (cpp_object != null){var id = cpp_object.GetProcessID();document.getElementById("process_info").innerText = "本进程ID为:" + id;}}function SaveCppObject(obj){cpp_object = obj;}var cpp_object;</script>
</head>
<body><p id="process_info"></p><button type="button" οnclick="ShowMessageBox()">MessageBox</button><button type="button" οnclick="GetProcessID()">Process ID</button>
</body>
</html>
    然后我在我的CxxDlg里写下了如下的两个成员函数:

DWORD CJsCallCppDlg::GetProcessID()
{return GetCurrentProcessId();
}void CJsCallCppDlg::ShowMessageBox(const wchar_t *msg)
{MessageBox(msg, L"这是来自javascript的消息");
}

    接来下,我要用HTML中的这两个按钮,分别调用这两个C++函数,其中一个是ShowMessageBox,让Javascript调用它并传递一个字符串给它,最终C++这边通过Windows API的MessageBox实现弹出一个消息框。另外一个是GetProcessID,Javascript调用它,最终C++这边通过Windows API的GetCurrentProcessId()获取本进程ID,并给Javascript返回这个ID值,然后显示到HTML中。

    由于我的CxxDlg继承了IDispatch,那么我需要实现IDispatch中的七个纯虚函数,所以在CxxDlg类的声明中添加如下七个虚函数的声明:
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);virtual ULONG STDMETHODCALLTYPE AddRef();virtual ULONG STDMETHODCALLTYPE Release();

    然后实现这七个虚函数:

//我自己给我的两个函数拟定的数字ID,这个ID可以取0-16384之间的任意数
enum
{FUNCTION_ShowMessageBox = 1,FUNCTION_GetProcessID = 2,
};//不用实现,直接返回E_NOTIMPL
HRESULT STDMETHODCALLTYPE CJsCallCppDlg::GetTypeInfoCount(UINT *pctinfo)
{return E_NOTIMPL;
}//不用实现,直接返回E_NOTIMPL
HRESULT STDMETHODCALLTYPE CJsCallCppDlg::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{return E_NOTIMPL;
}//JavaScript调用这个对象的方法时,会把方法名,放到rgszNames中,我们需要给这个方法名拟定一个唯一的数字ID,用rgDispId传回给它
//同理JavaScript存取这个对象的属性时,会把属性名放到rgszNames中,我们需要给这个属性名拟定一个唯一的数字ID,用rgDispId传回给它
//紧接着JavaScript会调用Invoke,并把这个ID作为参数传递进来
HRESULT STDMETHODCALLTYPE CJsCallCppDlg::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{//rgszNames是个字符串数组,cNames指明这个数组中有几个字符串,如果不是1个字符串,忽略它if (cNames != 1)return E_NOTIMPL;//如果字符串是ShowMessageBox,说明JavaScript在调用我这个对象的ShowMessageBox方法,我就把我拟定的ID通过rgDispId告诉它if (wcscmp(rgszNames[0], L"ShowMessageBox") == 0){*rgDispId = FUNCTION_ShowMessageBox;return S_OK;}//同理,如果字符串是GetProcessID,说明JavaScript在调用我这个对象的GetProcessID方法else if (wcscmp(rgszNames[0], L"GetProcessID") == 0){*rgDispId = FUNCTION_GetProcessID;return S_OK;}elsereturn E_NOTIMPL;
}//JavaScript通过GetIDsOfNames拿到我的对象的方法的ID后,会调用Invoke,dispIdMember就是刚才我告诉它的我自己拟定的ID
//wFlags指明JavaScript对我的对象干了什么事情!
//如果是DISPATCH_METHOD,说明JavaScript在调用这个对象的方法,比如cpp_object.ShowMessageBox();
//如果是DISPATCH_PROPERTYGET,说明JavaScript在获取这个对象的属性,比如var n = cpp_object.num;
//如果是DISPATCH_PROPERTYPUT,说明JavaScript在修改这个对象的属性,比如cpp_object.num = 10;
//如果是DISPATCH_PROPERTYPUTREF,说明JavaScript在通过引用修改这个对象,具体我也不懂
//示例代码并没有涉及到wFlags和对象属性的使用,需要的请自行研究,用法是一样的
//pDispParams就是JavaScript调用我的对象的方法时传递进来的参数,里面有一个数组保存着所有参数
//pDispParams->cArgs就是数组中有多少个参数
//pDispParams->rgvarg就是保存着参数的数组,请使用[]下标来访问,每个参数都是VARIANT类型,可以保存各种类型的值
//具体是什么类型用VARIANT::vt来判断,不多解释了,VARIANT这东西大家都懂
//pVarResult就是我们给JavaScript的返回值
//其它不用管
HRESULT STDMETHODCALLTYPE CJsCallCppDlg::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{//通过ID我就知道JavaScript想调用哪个方法if (dispIdMember == FUNCTION_ShowMessageBox){//检查是否只有一个参数if (pDispParams->cArgs != 1)return E_NOTIMPL;//检查这个参数是否是字符串类型if (pDispParams->rgvarg[0].vt != VT_BSTR)return E_NOTIMPL;//放心调用ShowMessageBox(pDispParams->rgvarg[0].bstrVal);return S_OK;}else if (dispIdMember == FUNCTION_GetProcessID){DWORD id = GetProcessID();*pVarResult = CComVariant(id);return S_OK;}elsereturn E_NOTIMPL;
}//JavaScript拿到我们传递给它的指针后,由于它不清楚我们的对象是什么东西,会调用QueryInterface来询问我们“你是什么鬼东西?”
//它会通过riid来问我们是什么东西,只有它问到我们是不是IID_IDispatch或我们是不是IID_IUnknown时,我们才能肯定的回答它S_OK
//因为我们的对象继承于IDispatch,而IDispatch又继承于IUnknown,我们只实现了这两个接口,所以只能这样来回答它的询问
HRESULT STDMETHODCALLTYPE CJsCallCppDlg::QueryInterface(REFIID riid, void **ppvObject)
{if (riid == IID_IDispatch || riid == IID_IUnknown){//对的,我是一个IDispatch,把我自己(this)交给你*ppvObject = static_cast<IDispatch*>(this);return S_OK;}elsereturn E_NOINTERFACE;
}//我们知道COM对象使用引用计数来管理对象生命周期,我们的CJsCallCppDlg对象的生命周期就是整个程序的生命周期
//我的这个对象不需要你JavaScript来管,我自己会管,所以我不用实现AddRef()和Release(),这里乱写一些。
//你要return 1;return 2;return 3;return 4;return 5;都可以
ULONG STDMETHODCALLTYPE CJsCallCppDlg::AddRef()
{return 1;
}//同上,不多说了
//题外话:当然如果你要new出一个c++对象来并扔给JavaScript来管,你就需要实现AddRef()和Release(),在引用计数归零时delete this;
ULONG STDMETHODCALLTYPE CJsCallCppDlg::Release()
{return 1;
}

    该讲的都在代码注释中讲了,简单来说,当JavaScript执行如cpp_object.GetProcessID();的代码时,会先调用GetIDsOfNames,并把"GetProcessID"这个字符串传递进来,我们给它分配一个自拟的ID,紧接着JavaScript会拿着这个ID来调用Invoke。至于参数和返回值如何传递,代码和注释写得很清楚了。

    注意我的HTML中的JavaScript代码中,我用一个var cpp_object;全局变量来保存C++对象,然后我还写了一个SaveCppObject()函数给C++调用,在WebBrowser加载完毕HTML文档后,需要先用C++调用JavaScript的这个SaveCppObject()函数,并把C++对象指针传递给JavaScript,这样JavaScript才能把它保存到var cpp_object;中,才能进行接下来的JavaScript调用C++。C++调用JavaScript的SaveCppObject()方法代码如下:

//调用JavaScript的SaveCppObject函数,把我自己(this)交给它,SaveCppObject会把我这个对象保存到全局变量var cpp_object;中
//以后JavaScript就可以通过cpp_object来调用我这个C++对象的方法了
void CJsCallCppDlg::OnBnClickedOk()
{CComQIPtr<IHTMLDocument2> document = m_webbrowser.get_Document();CComDispatchDriver script;document->get_Script(&script);CComVariant var(static_cast<IDispatch*>(this));script.Invoke1(L"SaveCppObject", &var);
}
    好了,至此,JavaScript调用C++已经完成了。这种方法,需要先把IDispatch*(示例代码中是this,但因为this是CJsCallCppDlg的实例,而CJsCallCppDlg多重继承于IDispatch,实际this就是IDispatch*了)传递给JavaScript,JavaScript把它保存好,然后调用它。网上还有一种方法是,在C++这边再实现IDocHostUIHandler接口,然后通过一系列麻烦的操作,JavaScript那边就可以直接通过window.external来调用C++,而不用var cpp_object;了。不过那个实现实在是太麻烦太恶心了,又会引入一大堆我解释不清楚的东西,所以还是作罢了,这样才是最简洁的实现。

    最后晒上一张运行效果图:



示例代码的整个VisualStudio项目文件可以到这里下载和查看(版本VS2015):https://github.com/charlessimonyi/javascript_call_cpp

MSDN上关于IDispatch接口的文档:https://msdn.microsoft.com/en-us/library/windows/desktop/ms221608(v=vs.85).aspx

    对了,还有一点,写好的HTML文件不仅可以直接和EXE放在一个目录下使用,也可以在VisualStudio中把HTML文件作为资源添加到项目中,这样最终写出来的程序只有一个EXE,HTML文件已经在EXE里面了,至于如何让WebBrowser加载这个HTML文件,可以在CxxDlg::OnInitDialog()中使用如下代码:

//加载资源文件中的HTML,IDR_HTML1就是HTML文件在资源文件中的ID
wchar_t self_path[MAX_PATH] = { 0 };
GetModuleFileName(NULL, self_path, MAX_PATH);
CString res_url;
res_url.Format(L"res://%s/%d", self_path, IDR_HTML1);
m_webbrowser.Navigate(res_url, NULL, NULL, NULL, NULL);

常见问题:
①调用m_webbrowser.Navigate()加载一个HTML文档后,不要紧接着就:
CComQIPtr<IHTMLDocument2> document = m_webbrowser.get_Document();
CComDispatchDriver script;
document->get_Script(&script);
这样获取其接口指针进行C++调用Javascript操作,这样往往会取到空指针,因为m_webbrowser.Navigate()调用完毕,并不意味着HTML文档已经加载、渲染完毕,m_webbrowser.Navigate()实际上是一个异步操作,调用以后只是发出了一个命令,让WebBrowser去加载这个HTML文档,至于何时加载完毕,可以处理WebBrowser的DocumentComplete事件来获知,只有在触发DocumentComplete事件后,才可以获取其接口指针进行操作。所以在上面的示例中,如果想让HTML文档加载完毕后就自动用C++调用Javascript的SaveCppObject()函数,把C++对象传递过去,只需把上面示例程序中我写在按钮响应函数中的代码写到DocumentComplete事件的响应函数中即可(Github上的示例代码已经更新成这样了)。
怎么添加DocumentComplete事件响应函数?看下图,先选中WebBrowser控件,再到属性对话框里找想处理的事件,所有的Activex控件的事件响应函数都可以在这里添加。



本系列其它文章:

《VC与JavaScript交互(一) ———— 如何实现》

《VC与JavaScript交互(二) ———— 调用JS函数》


本文由CharlesSimonyi发表于CSDN博客:http://blog.csdn.net/charlessimonyi/article/details/50984903转载请注明出处

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Linux内存映射——mmap

    一 mmap系统调用 1.内存映射所谓的内存映射就是把物理内存映射到进程的地址空间之内,这些应用程序就可以直接使用输入输出的地址空间,从而提高读写的效率。Linux提供了mmap()函数,用来映射物理内存。在驱动程序中,应用程序以设备文件为对象,调用mmap()函数,内核进行内存映…...

    2024/4/12 11:25:00
  2. 微信小程序json、map和字符串的相互转化

    微信小程序json、map和字符串的相互转化字符串转json function stringToJson(data){ return JSON.parse(data); }复制代码json转字符串function jsonToString(data){ return JSON.stringify(data); }复制代码map转为jsonfunction mapToJson(map) { return JSON.string…...

    2024/5/5 19:45:14
  3. js 不区分大小写比较字符串

    js是一种区分大小写的语言,如果用到不需要区分大小写的时候我们就要转换一下思路了。 比如:先把要比较的字符串统一一下大小写,然后在进行比较,这样是不是就省事多了,在js中有两个这样的方法: toUpperCase():把字符串转换为大写; toLowerCase() :把字符串转换为小写…...

    2024/5/5 17:46:14
  4. css样式中的滚轮事件和隐藏滚动条

    css样式中的滚轮事件最近滚轮事件,当时拿到项目第一反应就是用js/jq来写。结果写了一大堆代码,还要计算溢出情况。后来在同事的提醒下,发现自己犯了一个很严重的低级错误(居然忘了css中有现成的设置)。。。只需要在最父级元素样式中加上overflow-y: scroll;overflow-x:hi…...

    2024/5/5 17:23:35
  5. 一些JavaScript代码没有缩进代码不换行是什么鬼

    如果你看到一篇有以下特征的JavaScript代码:没有缩进 变量名都是a、b、c之类的单字母 没有换行,整篇代码是用一行“写”完的说明这样的JavaScript代码是经过刻意压缩了的,也就是人们常说的“代码混淆”, 为了尽可能恢复代码的可读性,可以直接搜索关键词“js反混淆工具”,…...

    2024/5/5 20:00:56
  6. Linux Kernel 内存管理之CMA

    linux kernel中的CMA即,连续内存区管理,其提供配置为CONFIG_CMA和CONFIG_CMA_DEBUG 毋庸置疑,其管理的是一块块连续内存块。这个在物理地址上是连续的。这点跟我们使用的伙伴算法 以及虚拟地址有点不一样。尽管伙伴算法中使用kmalloc申请连续物理内存也可以,但是在长时间 测…...

    2024/4/12 16:16:46
  7. 解决list转换json出现的各类问题 object转换为Map对象

    最近在写接口,要把list集合转换为json串返回。例如List<order> orders = orderService.findAll();JSONArray array = JSONArray.fromObject(orders);可能出现java.lang.StackOverflowError:该错误是由于当前线程的栈满了 ,也就是函数调用层级过多导致。在集合类型上…...

    2024/5/5 19:47:21
  8. 你不知道的JavaScript演示代码Github地址

    你不知道的JavaScript博文相关代码托管至Github,每次写完博客会把代码提交上去。代码地址:https://github.com/rongbo-j/you-dont-know-js点击Download Zip可下载源码,或者安装git版本控制工具,在控制台或终端敲两行命令可以检出代码:git init git clone https://github.c…...

    2024/5/5 19:43:37
  9. linux内存管理---虚拟地址、逻辑地址、线性地址、物理地址的区别(一)

    分析linux内存管理机制,离不了上述几个概念,在介绍上述几个概念之前,先从《深入理解linux内核》这本书中摘抄几段关于上述名词的解释: 一、《深入理解linux内核》的解释 逻辑地址(Logical Address) 包含在机器语言指令中用来指定一个操作数或一条指令的地址(有点深奥)。…...

    2024/5/5 18:38:55
  10. [js点击]JavaScript之手势事件大纲

    [js点击]JavaScript之原生手势事件详解03 http://blog.csdn.net/BaiHuaXiu123/article/details/53244316 [js点击]JavaScript之触摸事件之touch.js详解02 http://blog.csdn.net/BaiHuaXiu123/article/details/53244249 [js点击]JavaScript之原生触摸事件详解01 http://blog.csd…...

    2024/4/12 13:09:41
  11. 新鲜传媒CEO纪中展:经济危机对年轻人是机会

    新鲜传媒CEO纪中展:经济危机对年轻人是机会http://www.sina.com.cn 2008年11月12日 16:23 创业时代新鲜传媒创始人纪中展做客“老牛创业谈”:经济危机对年轻人是机会 点击观看本访谈视频  11月12日,新鲜传媒创始人、CEO纪中展做客新浪创业频道“老牛创业谈”,与《创业家…...

    2024/4/12 11:25:30
  12. JS or C#?不存在的脚本之争(UnityScript 不是 Javascript)

    转自:http://www.infoq.com/cn/articles/js-or-csharp-non-existent-scripts-debate?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global前言周五的下午,偶然间晃了一眼游戏蛮牛Unity3D的QQ群,又看到了一个Unity3D开发中老生长谈的问…...

    2024/4/18 22:45:08
  13. 如何将Map转化为json字符串

    利用gson解析/*** 将Map转化为Json字符串* * @param map* @return String*/ public static <T> String mapToJson(Map<String, T> map) {Gson gson = new Gson();String jsonStr = gson.toJson(map);return jsonStr; }gson jar包下载地址 :http://download.csdn.n…...

    2024/4/12 11:26:00
  14. 流媒体开发之-音悦台TV解析特定条件下的所有TV视频

    整合流媒体开发之-音悦台TV解析和流媒体开发之-音悦台TV页码链接解析这两部分来实现解析音乐台特定条件的所有TV视频链接。 package com.pigvideo.parser.yinyuetai;import com.pigvideo.model.YinYueTaiModel; import com.pigvideo.model.YinYueTaiPageModel;import org.jsoup…...

    2024/4/12 11:26:48
  15. css3 实现滚动条美化

    /*滚动条的宽度*/::-webkit-scrollbar {width:9px;height:9px;}/*外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果*/::-webkit-scrollbar-track {width: 6px;background-color:#0d1b20;-webkit-border-radius: 2em;-moz-border-radius: 2em;bor…...

    2024/4/19 13:00:42
  16. js setTimeout 延时不起作用原因------就是你太大意了

    在js中设置延时,一般都会用到setTimeout函数。但是,很多时候都会因为自己的粗心大意而出错: 要注意,其实setTimeout的第一个参数是code,所以应该传递javascript代码字符串(网上说法,亲测未能成功),或者是一个匿名的function(){},而不能直接写函数。//使用js代码字符串…...

    2024/4/12 11:25:48
  17. json格式的字符串转换Map 字段为null时会忽略的解决方法

    得到一个json格式的字符串 String bean = file.get("bean").toString();转换 Map<String, Object> map2 = (Map<String, Object>) JSONObject.parseObject(bean,new TypeReference<Map<String, Object>>() { });...

    2024/4/20 8:27:37
  18. 记一次MongoDB性能问题+Linux内存管理学习笔记--物理内存分配

    记一次MongoDB性能问题最近忙着把一个项目从MySQL迁移到MongoDB,在导入旧数据的过程中,遇到了些许波折,犯了不少错误,但同时也学到了不少知识,遂记录下来。公司为这个项目专门配备了几台高性能务器,清一色的双路四核超线程CPU,外加32G内存,运维人员安装好MongoDB后,就…...

    2024/4/16 5:27:28
  19. js设置a标签href不跳转 禁止跳转

    转自: http://www.cnblogs.com/lipanpan/p/4095524.html1.方法当页面中a标签不需要任何跳转时,从原理上来讲,可分如下两种方法:1.标签属性href,使其指向空或不返回任何内容。如:<a href="javascript:void(0);" >点此无反应javascript:void(0)</a>…...

    2024/4/12 13:13:47
  20. Linux是如何避免内存碎片的

    Linux是如何避免内存碎片的?在网上看到这个面试题,参考答案是这样的:伙伴算法,用于管理物理内存,避免内存碎片; 高速缓存Slab层用于管理内核分配内存,避免碎片。故继而去深入了解了一波,做了一个粗略的整理:内存碎片问题频繁地请求和释放不同大小的内存,必然导致内存碎…...

    2024/4/20 2:07:04

最新文章

  1. 云端部署Stirling PDF:构建个人App的API调用指南(附Python源码)

    今天发现一个Github的开源项目&#xff0c;Stirling PDF&#xff0c;项目地址如下&#xff1a;https://gitcode.com/Stirling-Tools/Stirling-PDFhttps://gitcode.com/Stirling-Tools/Stirling-PDF?utm_sourceartical_gitcode目前CSDN上已经有好几个up主都介绍了这个项目&…...

    2024/5/5 21:29:16
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. milvus search api的数据结构

    search api的数据结构 此api的功能是向量相似度搜索(vector similarity search) 一个完整的search例子: 服务端collection是一个hnsw类型的索引。 import random from pymilvus import (connections,Collection, )dim 128if __name__ __main__:connections.connect(alias…...

    2024/5/5 1:29:39
  4. 游戏引擎架构01__引擎架构图

    根据游戏引擎架构预设的引擎架构来构建运行时引擎架构 ​...

    2024/5/4 14:29:43
  5. CSS3 高级- 复杂选择器、内容生成、变形(transform)、过渡(transition)、动画(animation)

    文章目录 一、复杂选择器兄弟选择器:选择平级元素的唯一办法属性选择器:1、通用:基本用不着,太泛了2、自定义:4种伪类选择器:1、目标伪类:2、结构伪类:3、元素状态伪类:4、伪元素选择器:应用于文字,使网页看起来想杂志5、否定伪类:选择器:not([本选择器的条件]) /*…...

    2024/5/5 8:52:14
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/4 23:55:17
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/4 18:20:48
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57