سؤال

لقد قاتل مع Canon Edsdk لفترة من الوقت الآن. يمكنني بنجاح الحصول على المكتبة لحفظ ملف مباشرة على القرص، ومع ذلك، لا يمكنني الحصول على عقد بايت الصورة [] في الذاكرة. كلما حاولت marshal.copy () دفق EDSDK إلى البايت []، أحصل دائما على الخطأ التالي:

accessviolationException: حاول قراءة أو كتابة الذاكرة المحمية. هذا غالبا ما يكون مؤشرا على أن الذاكرة الأخرى تالفة.

فيما يلي أحد أشكال التعليمات البرمجية التي استخدمتها في محاولة الحصول على الدفق:

        private uint downloadImage(IntPtr directoryItem)
        {
            uint err = EDSDK.EDS_ERR_OK;
            IntPtr stream = IntPtr.Zero;

            // Get information of the directory item.
            EDSDK.EdsDirectoryItemInfo dirItemInfo;
            err = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);

            // Create a file stream for receiving image.
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsCreateMemoryStream(dirItemInfo.Size, out stream);
            }

            //  Fill the stream with the resulting image
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsDownload(directoryItem, dirItemInfo.Size, stream);
            }

            //  Copy the stream to a byte[] and 
            if (err == EDSDK.EDS_ERR_OK)
            {
                byte[] buffer = new byte[dirItemInfo.Size];

                GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                // The following line is where it blows up...
                Marshal.Copy(stream, buffer, 0, (int)dirItemInfo.Size);

                // ... Image manipulation, show user, whatever
            }

            return err;
        }

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

أيه أفكار؟

تحديث: أرى هذا السلوك في كلا الإصدارين 2.5 و 2.6.

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

المحلول

أنا فقط غوغلت ل EdsCreateMemoryStream و وجدت عينة حيث توجد مكالمة أخرى للحصول على المؤشر من "دفق الذاكرة".

IntPtr pointerToBytes;
EDSDKLib.EDSDK.EdsGetPointer(stream, out pointerToBytes);

يمكنك بعد ذلك استخدام pointerToBytes كمصدر للقراءة من الداخل Marshal.Copy.

لذلك، أعتقد أن ما تقوم به حاليا هو محاولة نسخ عدد كبير من البايتات بدءا من عنوان بعض هيكل التحكم الصغير المشار إليه stream, ، وبالتالي كنت تقرأ بعد نهاية هذا الهيكل.

يحرر: بالمناسبة، يبدو رمز كما لو قال لك شخص ما أنك يجب أن يكون لديك بيان عائد واحد فقط! هذه النصيحة القديمة المتعلقة باللغات مثل Fortran و C؛ هذا لا معنى له بلغات حديثة. سيكون الكود الخاص بك أكثر وضوحا (على الأقل في هذه الحالة) إذا عدت على الفور رمز الخطأ في كل مرة حصلت فيها على فشل:

if ((err = EDSDK.EdsBlahBlah(...)) != EDSDK.EDS_ERR_OK)
    return err;

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

نصائح أخرى

أدرك أن هذا منصب قديم، ولكن هذا هو مقتطف C # كاملة للتحميل من دفق الذاكرة. قد يكون مفيدا لشخص آخر. يجب تعيين الكاميرا إلى Edsdk.edssaveto.host أو edsdk.edsssaveto.both

        uint error = EDSDK.EDS_ERR_OK;
        IntPtr stream = IntPtr.Zero;

        EDSDK.EdsDirectoryItemInfo directoryItemInfo;

        error = EDSDK.EdsGetDirectoryItemInfo(this.DirectoryItem, out directoryItemInfo);

        //create a file stream to accept the image
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsCreateMemoryStream(directoryItemInfo.Size, out stream);
        }


        //down load image
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsDownload(this.DirectoryItem, directoryItemInfo.Size, stream);
        }

        //complete download
        if (error == EDSDK.EDS_ERR_OK)
        {
            error = EDSDK.EdsDownloadComplete(this.DirectoryItem);
        }


        //convert to memory stream
        IntPtr pointer; //pointer to image stream
        EDSDK.EdsGetPointer(stream, out pointer);

        uint length = 0;
        EDSDK.EdsGetLength(stream, out length);

        byte[] bytes = new byte[length];

        //Move from unmanaged to managed code.
        Marshal.Copy(pointer, bytes, 0, bytes.Length);

        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(bytes);
        Image image = System.Drawing.Image.FromStream(memoryStream);

        if (pointer != IntPtr.Zero)
        {
            EDSDK.EdsRelease(pointer);
            pointer = IntPtr.Zero;
        }


        if (this.DirectoryItem != IntPtr.Zero)
        {
            EDSDK.EdsRelease(this.DirectoryItem);
            this.DirectoryItem = IntPtr.Zero;
        }

        if (stream != IntPtr.Zero)
        {
            EDSDK.EdsRelease(stream);
            stream = IntPtr.Zero;
        }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top