سؤال

أحاول إرسال كائن COM على MSMQ رسالة في C++.هذا هو بلدي وجوه :

class ATL_NO_VTABLE CAnalisis :
    public CComObjectRootEx,
    public CComCoClass,
    public ISupportErrorInfo,
    public IDispatchImpl,
    public IPersistStreamInit
{
private:
    typedef struct {
        DOUBLE size;
        float color;
        float light;

        BSTR imgName;

        BSTR  uname;

    } Image;

    Image img;
    STDMETHOD(Load)(IStream *pStm);
    STDMETHOD(Save)(IStream *pStm,  BOOL fClearDirty);

كل شيء يسير على ما يرام و لا يمكن الحصول على كل كائن ولكن BSTR أنواع.يطفو الأعداد الصحيحة بشكل صحيح المرسلة والمستلمة.ولكن BSTR أنواع لا تعمل.أحاول أن أرسل سلاسل لا يمكن العثور على الطريق.لقد حاولت مع البديل بدلا من ذلك كان نتيجة خطأ أيضا.بطريقة ما يبدو أن الجمل ليست تسلسل.

هذه هي بعض من الحصول على وتعيين وظائف بلدي ATL المكون:

هذا يعمل بشكل جيد:

STDMETHODIMP CAnalisis::getLight(FLOAT* light)
{

    *light=img.light;
    return S_OK;
}

STDMETHODIMP CAnalisis::setLight(FLOAT light)
{
    img.light=light;
    return S_OK;
}

لا هذا واحد :

STDMETHODIMP CAnalisis::getImgName(BSTR* imgName)
{
    *imgName = img.imgName;

    return S_OK;
}

STDMETHODIMP CAnalisis::setImgName(BSTR imgName)
{

    img.imgName=imgName;
    return S_OK;
}

و هذه هي الطريقة التي يمكنني إنشاء MSMQ رسالة وملء القيم في المنتج :

// For these ActiveX components we need only smart interface pointer
        IMSMQQueueInfosPtr  pQueueInfos; 
        IMSMQQueueInfoPtr   pQueueInfo; 
        IMSMQQueuePtr       pQueue;
        IUnknownPtr         pIUnknown;
        // Instanciate the follwing ActiveX components
        IMSMQQueryPtr       pQuery(__uuidof(MSMQQuery));
        IMSMQMessagePtr     pMessage(__uuidof(MSMQMessage));


        IAnalisisPtr pAnalisis(__uuidof(Analisis));

                WCHAR *  imagen;        
        imagen = L"imagen1.jpg";
                pAnalisis->setImgName(imagen);


                 (...)

                pAnalisis->setFruitSize(20.00);

                 (...)

                pQueueInfo = new IMSMQQueueInfoPtr( __uuidof(MSMQQueueInfo) );

        pQueueInfo->PathName = "MYCOMPUTER\\private$\\myprivatequeue";

            pQueue = pQueueInfo->Open(MQ_SEND_ACCESS, MQ_DENY_NONE);
        pMessage->Body = static_cast(pAnalisis);
                pMessage->Send(pQueue);


هنا هو رمز التسلسل

STDMETHODIMP CAnalisis::Load( IStream *pStm )
{
    ULONG           cb;
    HRESULT         hr;
    if (NULL==pStm)
        return ResultFromScode(E_POINTER);
    // Read an object from the stream.
    //
    hr=pStm->Read(&img, sizeof(Image), &cb);
    if (FAILED(hr))
        return hr;
    if (sizeof(Image) != cb)
        return E_FAIL;

    return NOERROR;
}

STDMETHODIMP CAnalisis::Save( IStream *pStm, BOOL bClearDirty )
{
    ULONG           cb;
    HRESULT         hr;
    if (NULL==pStm)
        return ResultFromScode(E_POINTER);

    // Write an object into the stream.
    hr=pStm->Write(&img, (ULONG)sizeof(Image), &cb);
    if (FAILED(hr) || sizeof(Image)!=cb)
       return ResultFromScode(STG_E_WRITEFAULT);

    return NOERROR;
}

إذا كنت تحصل على BSTR قيمة في المنتج (قبل التسلسل), pAnalisis-getImgName(), أنه يعمل بشكل جيد.في المقابل, عندما كنت في محاولة للحصول عليه في المستهلك ، بعد قراءة الرسالة من قائمة الانتظار ، فإنه لا يعود أي شيء.القيم الأخرى مثل الحجم, يتم إرجاع مع أي مشكلة.

لا أحد يعرف كيفية إرسال BSTR قيمة داخل كائن COM من خلال MSMQ ?

لقد حاولت أن تجد بعض الأمثلة المشابهة تماما ولكن دون جدوى.

الشيء هو أنني أتلقى إما غريب جدا قيمة مع شخصيات غريبة أو قيمة ست عشرية ، اعتمادا على كيفية استخراج قيمة ..الشيء هو أن كنت لا تحصل على القيمة الصحيحة.

وأنا أتساءل, ومع ذلك...هل نحن على يقين أنه من الممكن أن ترسل BSTR قيمة ؟ إذا لم أكن مخطئا ، بل هو مؤشر إلى سلسلة...أنا أجري عمليتين مختلفتين (أيالمنتج والمستهلك) ، حتى أنها تستخدم مختلف كتل الذاكرة ، وهي من المفترض أن تكون تعمل على آلات مختلفة جدا...

كنت أحاول إرسال هذه المعلومات حسب متغير نوع..ولكن أيضا ضاعت.ومع ذلك ، يبدو أقل قليلا بعيد المنال من إرسال BSTR.

أي أفكار حول هذا ؟

هل كانت مفيدة؟

المحلول

والمشكلة هي أن التسلسل من الدرجة صورة يعامل على أنه كتلة قريبة من الذاكرة. منذ BSTR هو في الحقيقة مؤشر فقط قيمة المؤشر هي متسلسلة ويتم فقدان حمولة BSTR.

وبدلا من ذلك يجب أن تكتب جميع المجالات باستثناء BSTRs كما ثنائي وBSTRs عملية على حدة. على سبيل المثال، يمكنك كتابة طول BSTR عدد صحيح أولا، ثم حمولتها. عند قراءة سوف تقرأ طول أولا، استدعاء SysAllocStringLen () لتخصيص مخزن مؤقت، ثم قراءة الحمولة.

واترك التسلسل من حقول بسيطة كما هو (وIPersistStreamInit :: حفظ ()):

pStm->Write(&(img.color), (ULONG)sizeof(float), &cb);

لBSTRs القيام بذلك:

int length = SysStringLen( img.uname );
pStm->Write(&length, (ULONG)sizeof(int), &cb);
if( length > 0 ) {
   pStm->Write( img.uname, (ULONG)(length * sizeof(WCHAR) ), &cb);
}

وعلى غرار لقراءة (وIPersistStreamInit :: تحميل ()):

int length;
pStm->Read(&length, (ULONG)sizeof(int), &cb);
if( length > 0 ) {
   img.uname = SysAllocStringLen( 0, length );
   pStm->Read( img.uname, (ULONG)( length * sizeof( WCHAR) ), &cb);
} else {
   img.uname = 0;
}

لاحظ أن هذا الرمز يكتب / يقرأ طول السلسلة ثم يكتب / يقرأ الحمولة التي تتكون من أحرف Unicode. أحرف Unicode تحتل بايت أكثر من واحد في كل - وبالتالي الضرب في IStream مقروءة الأساليب / الكتابة استدعاء

نصائح أخرى

إذا كنت ببساطة تمرير WCHAR -- طول المعلومات المفقودة.على BSTR هو تالف وهذا ربما يسبب لك كل هذا الحزن.تحتاج إلى استخدام SysAllocString استخدام جميع العناصر.انظر MSDN -- على ملاحظات القسم.محاولة:

BSTR imagen = SysAllocString(L"imagen1.jpg");

حسنا، هذا الجواب يعتمد على تفعلون شيئا غريبا في هذه الأيام، ولكن قد تكون قابلة للتطبيق. وقبل طويل، منذ وقت طويل كان لي لتمرير سلسلة VB تحت VB6 وVC ++ 6 (الموالي) من تطبيق VB. إلى التطبيق VC ++. وجاء طول طريق OK لكني غالبا ما تلقى حرف واحد على الجانب الآخر.

وكانت المشكلة أن التطبيق المتلقي. لم جمعتها ليونيكود، وإنما كمشروع ANSI. رمز طبقة COM أن تفكيك أنه على الجانب الآخر من نقل لم خدعة للاهتمام أن أنا فقط وجدت موثقة في زاوية غامضة من MSDN في مقتطفات الكتاب: أنه خلق ABSTR

وهناك ABSTR ليست في الواقع نوع. لا توجد وسيلة لإعلان واحد. انها في الواقع إعادة صياغة التخزين الأساسي لBSTR بحيث يمكنك التظاهر انها ASCII شار * في C ++. ويتم ذلك بجعل أولا من النقاط BSTR إلى الحرف الأول بعد رأس لها (نموذجي على أي حال لمثل هذه الهياكل في C ++، IIRC) و <م> ثم خلط بيانات سلسلة الفعلية بحيث يحتوي على جميع من أول بايت تليها كل من وحدات البايت الثانية. اسم آخر لهذا هو "الشر المحض".

واثنان <م> جدا سيئة أشياء يمكن أن يحدث بهذه الطريقة: إذا تم هذا التحويل، ويمكنك علاج نتيجة كما لو انها لا تزال واسعة سلسلة أحرف، وتحصل على رطانة. إذا هو لم يفعل ذلك، ويجب التعامل مع نتائج مجموعة أحرف ASCII، تحصل عادة حرف واحد، اذا تضمنت الأصلي الوحيدة أحرف ASCII المدى، لأنه في تمثيل واسع لكل بايت الآخر هو صفر و البايتات عالية تأتي في المرتبة الثانية.

وأنا لا أستطيع أن أقول تماما عن وصفك إذا كان هذا هو ما حدث لك. ولكن أوصى وقف الشيء في مصحح وتبحث في كافة البيانات سلسلة تحت تلك القيمة تلقى لمعرفة ما إذا تم تعديلات عليها بطريقة غير متوقعة. إذا تم أسكن، واسأل نفسك لماذا والنظر في الطريقة التي بنيت المشروع.

وحقيقة شكل غير شرعي تقريبا مثبتة الى نوع القائمة وتخطيط الذاكرة البديلة التي من الصعب حقا أن تجد، حتى من قبل كيف العديد من سلسلة تنسيقات يمكن أن-WE-الماكياج معايير التنمية MS، فقط قدم عني الصراخ. وكان ما يقرب سيئا كما تحاول تحديد "GetModuleFileName" لأول مرة عن وظيفة لاستخدام للحصول على مسار الملف القابل للتنفيذ الحالي.

وجوه الخاص بك يحتاج إلى إنشاء نسخة من السلسلة في كل من جالبة واضعة:

STDMETHODIMP CAnalisis::getImgName(BSTR* imgName)
{
    *imgName = SysAllocString(img.imgName);

    return S_OK;
}

STDMETHODIMP CAnalisis::setImgName(BSTR imgName)
{
    SysFreeString(img.imgName);
    img.imgName=SysAllocString(imgName);
    return S_OK;
}

وبطبيعة الحال، تحتاج إلى تحرير السلسلة في المدمر، تحقق من وجود NULL ptrs الخ.

وبدلا من ذلك يمكنك استخدام CComBSTR بدلا من BSTR. CComBSTR هو أذكى من BSTR، فإنه يعتني تخصيص وإلغاء تخصيص الذاكرة.

واقتراحي هو وضع الحقول في متغير (حتى لو كان مؤقتا) ثم استخدام البديل كود تدفق لشد البيانات، وإلغاء تسلسل على الطرف الآخر.

وهنا هو كود تدفق يمكنك استخدام (آسف ولكن عن 20 سنة :))

الرابط: https://github.com/kasajian/VariantStream/blob /master/VariantStream.h

والرمز قليلا مطول للصق هنا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top