精华内容
下载资源
问答
  • 如何判断两个COM指针是同一个对象

    千次阅读 2009-06-02 11:38:00
    故事起源于我移植V8到IE中的过程,在CSDN论坛上也发现不少问此问题的人,所以特地整理一篇文章来解释这个问题。...假设要写一个判断函数的情况下,表示成这样:bool is_com_equal(IUnknown* unk1, IUnknown* un

    故事起源于我移植V8到IE中的过程,在CSDN论坛上也发现不少问此问题的人,所以特地整理一篇文章来解释这个问题。

     

    这个问题本来是一个非常简单的问题,COM指针也是指针,既然是指针,只要它们的值相同,就表示它们指向相同的COM对象,如果不同则表示不同对象。假设要写一个判断函数的情况下,表示成这样:

     

     

    这种判断方法在绝大多数情况下正确,但仅仅是绝大多数,还有极少数情况下判断会失效,尤其在同一个对象有两个不同指针的情况下。什么情况呢?代理对象。微软的很多产品大量使用了代理对象,注意这里的代理对象不是指的COM对象的代理存根。代理对象的作用像一个沙箱,能有效隔离引用计数和其它方法访问异常,而且也能在安全访问方面做更多的控制。Office对Application对象使用了代理对象,IE对IHTMLWindow2对象使用了代理对象,还有其它一些DOM对象也使用了代理对象。

     

    言归正传,一个COM对象既然可以存在一至多个代理对象,就必须提供方法来让用户判断这些COM对象是不是相同的对象(注意代理对象应该跟原始对象相同)。为此微软设计了IObjectIdentity接口,通过此接口的IsEqualObject方法来判断两个对象是否相同。下面的方法就是一个改进版。

     

     

    到目前为止,上面的 is_com_equal 函数工作得非常好,几乎挑不出什么毛病。但我这人太固执,还真挑出了它的毛病。其实这个毛病是一个伪毛病,函数本身没有问题,但是当我在把V8移植到IE中的时候揪出了IE的一条虫,大概过程是这样的:有两个对象,一个是div对象,另一个是style对象,这两个风马牛不相及的对象居然被 IObjectIdentity::IsEqualObject 判断成了相同的对象,可以想见后果如何。这个问题折腾了我大概一周的时间才找到原因。这个现象其实是微软在实现对象的 IObjectIdentity 接口时写错代码了,迫不得已我只好另辟途径来绕过这个BUG,在判断它之前通过对比IDispatch对象的IID来临时解决接口比较问题。下面的代码体现了这种比较,但是通常读者使用上面的代码就足够了,除非他也遇到了同样的问题。

     

     

     

    两个COM接口比较,居然用了如此多的代码和如此多的篇幅介绍,也真够BT的……

    展开全文
  • jni如何判断两个jobject是否为同一个java对象 jni开发时有时候需要将java对象缓存到native层,方便native层通过jni的反射方法进行回调操作。通常我们会将回调接口callback在native层存放为global reference全局...

      jni如何判断两个jobject是否为同一个java对象

     

        jni开发时有时候需要将java对象缓存到native层,方便native层通过jni的反射方法进行回调操作。通常我们会将回调接口callback在native层存放为global reference全局引用,熟悉jni开发的都知道,jni传入到native 层的jobject生命周期仅仅是函数的生命周期,当jni函数返回后对应的jobject对象就会失效,不能再操作,所以就必须申请为global reference。

    NewGlobalRef 将变量申请为全局引用,此时java虚拟机会保留jobject所指向的对象防止被垃圾回收器回收。 DeleteGlobalRef 释放全局引用,允许java虚拟机回收该引用指向的java对象,对于不需要使用的global reference必须调用该方法,否则会引起java虚拟机内存泄漏。

          既然global reference的实质是指向java对象,那么我们在将某个变量声明为global reference时如何判断该jobject是否已经是当前设置的global reference呢。经过一番查询,看到了一下方法

    IsSameObject 如果两个jobject指向同一个java 对象那么返回true,否则返回false。

     

    既然有方法了,接下来就是验证工作了。

    Hello.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Hello */
    
    #ifndef _Included_Hello
    #define _Included_Hello
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Hello
     * Method:    native_setObjectToGlobalRef
     * Signature: (LHello/Book;)V
     */
    JNIEXPORT void JNICALL Java_Hello_native_1setObjectToGlobalRef
      (JNIEnv *, jclass, jobject);
    
    /*
     * Class:     Hello
     * Method:    native_release
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_Hello_native_1release
      (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    Hello.cpp

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #include <cstdio>
    #include "Hello.h"
    
    // 全局变量,用于存储全局引用的
    jobject g_book_ref = NULL; 
    
    /*
     * Class:     Hello
     * Method:    native_setObjectToGlobalRef
     * Signature: (LHello/Book;)V
     */
    JNIEXPORT void JNICALL Java_Hello_native_1setObjectToGlobalRef
      (JNIEnv *env, jclass jclazz, jobject jbook) {
    
    	// 如果输入参数为null,那么不需要继续操作
    	if (NULL == jbook) {
    		printf("native_setObjectToGlobalRef jbook is NUll and g_book_ref is NOT NULL. we need to delete reference of old g_book_ref\n");
    		if (NULL != g_book_ref) {
                env->DeleteGlobalRef(g_book_ref);  // 删除老的全局引用
    		    g_book_ref = NULL;
            }
    		return;
    	}
    
       // 如果全局引用已经设置了,那么需要判断jni函数参数的jbook是否与当前的全局引用指向同一个java对象
       if (NULL != g_book_ref) {
            // 如果指向同一个对象,那么不需要再次为该jbook申请全局引用
    		if (env->IsSameObject(g_book_ref, jbook)) {
    			printf("native_setObjectToGlobalRef isSameObject: true, g_book_ref: %p, jbook: %p\n", g_book_ref, jbook);
    		} else {
                // 如果指向不同对象,那么先释放老的全局引用,再为jbook申请全局引用
    			printf("native_setObjectToGlobalRef isSameObject: false\n");
    			printf("native_setObjectToGlobalRef g_book_ref and jbook is not same object. we need to delete reference of old g_book_ref\n");
    			env->DeleteGlobalRef(g_book_ref);
    			printf("native_setObjectToGlobalRef create global reference to g_book_ref\n");
    			g_book_ref = env->NewGlobalRef(jbook);
    		}
    	} else {
    		printf("native_setObjectToGlobalRef g_book_ref is NULL\n");
    		printf("native_setObjectToGlobalRef create global reference to g_book_ref\n");
    		g_book_ref = env->NewGlobalRef(jbook);
    	}
    }
    
    /*
     * Class:     Hello
     * Method:    native_release
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_Hello_native_1release
      (JNIEnv *env, jclass jclazz) {
        printf("native_release g_book_ref: %p\n", g_book_ref);
    	if (NULL != g_book_ref) {
    		env->DeleteGlobalRef(g_book_ref);
    		g_book_ref = NULL;
    	}
    }
    
    
    #ifdef __cplusplus
    }
    #endif
    


    Hello.java

    public class Hello {
    	static {
    		try {
    			String sysName = System.getProperty("os.name");
    			if (sysName.contains("Linux")) {
    		        System.load(System.getProperty("user.dir") + "/libHello.so");
    			} else if (sysName.contains("Drawin") || sysName.contains("Mac")) {
    		        System.load(System.getProperty("user.dir") + "/libHello.dylib");
    			}
    		} catch (java.lang.UnsatisfiedLinkError e) {
    			e.printStackTrace();
    			System.err.println("load so failed.");
    			System.exit(1);
    		}
    	}
    
    	static class Book {
    		public String name;
    
    		public Book() {}
    		public Book(String name) {
    			this.name = name;
    		}
    	}
    
    	public native static void native_setObjectToGlobalRef(Book book);
    	public native static void native_release();
    
    	public static void main(String args[]) {
    		Book b1 = new Book();
    		Book b2 = new Book();
    		System.out.println("set b1");
    		native_setObjectToGlobalRef(b1);
    		System.out.println("set b2");
    		native_setObjectToGlobalRef(b2);
    		System.out.println("##set b2");
    		native_setObjectToGlobalRef(b2);
    		System.out.println("##set null");
    		native_setObjectToGlobalRef(null);
    		native_release();
    	}
    }
    

     

    makefile

    UNAME_S := $(shell uname -s)
    ifeq ($(UNAME_S),Darwin)
    main:
    	gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" Hello.cpp -dynamiclib -o libHello.dylib
    endif
    
    ifeq ($(UNAME_S),Linux)
    main:
    	gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" Hello.cpp -shared -fPIC -o libHello.so
    endif
    

     

    运行命令

    $ make

    $ javac Hello.java

     

    运行程序

    $ java -Djava.library.path=".:${JAVA_HOME}" Hello

    输出结果

    set b1
    native_setObjectToGlobalRef g_book_ref is NULL
    native_setObjectToGlobalRef create global reference to g_book_ref
    set b2
    native_setObjectToGlobalRef isSameObject: false
    native_setObjectToGlobalRef g_book_ref and jbook is not same object. we need to delete reference of old g_book_ref
    native_setObjectToGlobalRef create global reference to g_book_ref
    ##set b2
    native_setObjectToGlobalRef isSameObject: true, g_book_ref: 0x7fb16ae08e90, jbook: 0x70000ce4a900
    ##set null
    native_setObjectToGlobalRef jbook is NUll and g_book_ref is NOT NULL. we need to delete reference of old g_book_ref
    native_release g_book_ref: 0x0

    1. set b1时

    因为是首次设置,此时native的g_book_ref还是null,没有被指向java对象,所以需要用全局引用为jbook保存java对象引用;

    2. set b2时

    isSameObject返回false,证明g_book_ref和jbook指向的对象不一样(此时jbook指向b2,而g_book_ref指向步骤1设置的b1),所以需要先删除老的b1全局引用再为b2申请全局引用;

    3. 再次设置b2时

    isSameObject返回true,证明g_book_ref和jbook指向的对象一样(此时jbook和g_book_ref都指向b2,注意两者的native地址不一样),为了节省操作,所以不需要在为jbook申请全局引用;

    4. 设置为null

    因为jbook为null,所以需要释放全局引用g_book_ref。

    5. native释放

    在Book native释放时因为步骤4已经提前释放了全局引用,所以不需要再释放了。

     

     

    展开全文
  • 环境准备:需要引入dayjs,如何引用请另外搜索...前提:两个时间,一个为timeBefore,一个为timeAfter,timeBefore<=timeAfter。 大致思路:利用timeAfter计算出本周的起始时间weekStart,只要timeBefore大于wee...

    环境准备:需要引入dayjs,如何引用请另外搜索,只说实现思路。

    定义:周一~周日算为一周。注意函数中周日返回的值是0,也就是周日~周六,所以我们需要另外判断处理。

    前提:两个时间,一个为timeBefore,一个为timeAfter,timeBefore<=timeAfter。

    大致思路:利用timeAfter计算出本周的起始时间weekStart,只要timeBefore大于weekStart,即说明两个时间在同一周。

    具体代码:

    //是否为同一周,传入的日期不能超过今天,否则逻辑不成立
    function isSameWeek(timeBefore, timeAfter) {
        dayInWeek = timeAfter.day()
        //如果是周日,就改成7
        if (dayInWeek == 0) {
            dayInWeek = 7
        }
        
        //计算今天的凌晨时间
        todayZeroTime = new Date(timeAfter.year(), timeAfter.month(), timeAfter.date())
        //本周开始的时间=今天凌晨时间-今天是周几-1,这里需要-1是因为凌晨已经刨去一天
        weekStart = dayjs(todayZeroTime).subtract(dayInWeek - 1, 'day')
        //只要比这周的起始时间晚,就说明是本周内
        return timeBefore.isAfter(weekStart)
    }

    这里注意timeAfter需要比timeBefore时间来的晚,如果不做这个限制的话,其实也可以判断,随便拿个传入的时间计算出本周的起始时间和结束时间,另外一个参数时间跟起始结束时间做比较即可。

    展开全文
  • 如果两个id值一样,则表明分片产生的列表使用的同一地址同一份数据 ; 否则,则表明分片重新产生了一份数据,即一个新的列表,然后把数据拷贝到新列表中。 二、python的id函数判断分片产生的列表 l = [3,5,6,8,5...

    python学习网
    一、python的id函数判断分片产生的列表原理

    id在python中负责显示一个变量或者数据的唯一确定编号,分片操作是生成一个新的list,通过id可以直接判断出分片是重新生成了一份数据还是使用同一份数据。

    如果两个id值一样,则表明分片产生的列表是使用的同一地址同一份数据 ;

    否则,则表明分片是重新产生了一份数据,即一个新的列表,然后把数据拷贝到新列表中。

    二、python的id函数判断分片产生的列表

    l = [3,5,6,8,5,43,4,7]
    
    ll = l[:]     
    
    print(id(ll))
    
    print(id(lll))
    

    通过id验证ll和lll是同一份数据

    l[1] = 100print(l)
    
    print(ll)
    
    print(lll)
    
     
    
    ll[1] = 100print(ll)
    
    print(lll)
    
    展开全文
  • 而且JavaScript同一个页面的下方,格式如下: ``` module.experts(){ data:function(){ ###}, filter:{###}, computed:{###}, methods:{###} } ``` 我的equalcheck() ``` function equalcheck...
  • constructor判断要确保类型判断的对象在同一个realm下。不过我们如果想匹配不同realm,在一些特殊情况下,我们可以使用constructor的只读属性name: <pre><code>js parent.arr.constructor.name =...
  • 递归函数在编程中比较常用的一类函数,其...引用不过两个不同名的变量指向同一块存储地址。本来每个变量有各自的存储地址,赋值删除各行其道。 现在可好,两个变量共享一块存储地址。 $a=&$b; 。实际上指的 $a
  • 不对称性尽管KL散度从直观上个度量或距离函数,但它并不是一个真正的度量或者距离,因为它不具有对称性,即D(P||Q)!=D(Q||P) (2)非负性 相对熵的值是非负值,即D(P||Q)>0 from scipy.stats impor...
  • WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同一个网络资源的连接 WNetCancelConnection 结束一个网络连接 WNetCancelConnection2...
  • Windows API函数大全

    热门讨论 2010-02-04 09:04:57
    SetTextJustification 通过指定一个文本行应占据的额外空间,可用这个函数对文本进行端对齐处理 TabbedTextOut 支持制表站的一个文本描绘函数 TextOut 文本绘图函数 6. API之菜单函数 AppendMenu 在指定的菜单...
  • 回调函数

    2012-03-28 09:47:32
    所谓回调函数,比较拗口的说法:被调用的函数调用调用者提供的函数指针。 这种函数形式可以应对被调用函数无法在细节上...换言之,A不知道在给了我们两个某类型的数据之后如何判断他们的大小,如果针对每种数据
  • 其实都在解决同一个问题:维护状态,更新视图。在一般的应用当中,如果能够很好方案来应对这个问题,那么就几乎降低了大部分复杂性。 <h2>3 Virtual DOM算法 <p>DOM很慢的。如果我们把一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 414
精华内容 165
关键字:

如何判断两个函数是同一个函数