用P/Invoke訪問native API的問題 - RECT不等于System.Drawing.Rectangle。

博主将以前用Native API编写的PocketPC应用程序移植到.NET Compact Framework平台,遇到一些问题并解决。还下载了API Explorer查找所需的Native API声明方法,如GetWindowRect的声明方法,同时给出了相关转载链接。

(華版)

在昨晚我將以前编冩的某一個PocketPC應用程序(用Native API)换去.NET Compact Framework平台;因為以前只有Native API,所以就碰上一點點問題。。。但總算是迎刃而解!而以下是一點點地收獲和大家分享。

昨晚我下載了PaulYao编冩的API Explorer來找我所需要的Native API聲明方法。刚巧我就需要此GetWindowRect的聲明方法,而問題就是出現在GetWindowRect此API的聲明方法:
 


   o_paulyao.jpg

None.gif < DllImport( " user32.dll " ) >  _
ExpandedBlockStart.gifContractedBlock.gif
Public   Function GetWindowRect() Function GetWindowRect( _
InBlock.gif   
ByVal hWnd As IntPtr _
InBlock.gif   , 
ByRef lpRect As System.Drawing.Rectangle _
InBlock.gif   ) 
As Integer
ExpandedBlockEnd.gif
End Function

其實應該是以下的聲明方法才對:

None.gif < StructLayout(LayoutKind.Sequential) >  _
ExpandedBlockStart.gifContractedBlock.gif
Public   Structure RECT Structure RECT
InBlock.gif   
Public left As Integer
InBlock.gif   
Public top As Integer
InBlock.gif   
Public right As Integer
InBlock.gif   
Public bottom As Integer
ExpandedBlockEnd.gif
End Structure

None.gif
None.gif
< DllImport( " user32.dll " ) >  _
ExpandedBlockStart.gifContractedBlock.gif
Public   Function GetWindowRect() Function GetWindowRect( _
InBlock.gif   
ByVal hWnd As IntPtr _
InBlock.gif   , 
ByRef lpRect As RECT _
InBlock.gif   ) 
As Integer
ExpandedBlockEnd.gif
End Function

只是這样的一個錯誤。。。好攘我調試了好幾個小時也摸不凊到底出錯在那里。。。直到今天早上才發覺此API聲明有問題。因為前者把原有的RECT换去System.Drawing.Rectangle。而刚巧System.Drawing.Rectangle的structure size是大過RECT;所以前者是不會有异常錯誤(Exception Error)發生。但就返回一些不正确的數據。

   o_pinvoke.jpg

闗于進一步去感受两者的區别,我就编冩了一個小小的程序來做個实验。從圖片里我們可以看到用System.Drawing.Rectangle所得到的數據跟用RECT所得到的數據是不一样。此外,我也用Form object里的Top, Left, Right和Bottom的值數來做對比;然而得到的數據就和RECT的一模一样。除了用程序來就証,我也用了Spy++(圖)來做另一項就証;這也証明了用RECT所得到的數據是正确而不是System.Drawing.Rectangle。

   o_spyresult.jpg

除此之外,我也發覺當聲明Native API時要特别留意ANSI和UNICODE的聲明方法。比如説用 FindWindowW在WindowsXP平台去讀取某一個窗口的HWND是&H0;如果用 FindWindowA就可讀取相闗的HWND值數。那是因為 FindWindowW是用于UNICODE平台(PocketPC和WindowsCE)。

None.gif < DllImport( " user32.dll " ) >  _
ExpandedBlockStart.gifContractedBlock.gif
Public   Function FindWindowA() Function FindWindowA( _
InBlock.gif   
ByVal lpClassName As String _
InBlock.gif   , 
ByVal lpWindowName As String _
InBlock.gif   ) 
As IntPtr
ExpandedBlockEnd.gif
End Function

None.gif
None.gif
< DllImport( " user32.dll " ) >  _
ExpandedBlockStart.gifContractedBlock.gif
Public   Function FindWindowW() Function FindWindowW( _
InBlock.gif   
ByVal lpClassName As String _
InBlock.gif   , 
ByVal lpWindowName As String _
InBlock.gif   ) 
As IntPtr
ExpandedBlockEnd.gif
End Function

就在解决了我得問題。。。同時也發現了一個討論有闗P/Invoke的網頁 www.pinvoke.net和一個纇似VB6.0 ApiViewer的開發工具 ApiExplorer。如果你是Win32API的爱好者,就不能錯過這两样好的東西哦。

點撃下載代碼

转载于:https://www.cnblogs.com/hackzai/archive/2005/03/15/119195.html

void CanvasContext::draw(bool solelyTextureViewUpdates) { 683 #ifdef __ANDROID__ 684 if (auto grContext = getGrContext()) { 685 if (grContext->abandoned()) { 686 if (grContext->isDeviceLost()) { 687 LOG_ALWAYS_FATAL("Lost GPU device unexpectedly"); 688 return; 689 } 690 LOG_ALWAYS_FATAL("GrContext is abandoned at start of CanvasContext::draw"); 691 return; 692 } 693 } 694 #endif 695 SkRect dirty; 696 mDamageAccumulator.finish(&dirty); 697 698 // reset syncDelayDuration each time we draw 699 nsecs_t syncDelayDuration = mSyncDelayDuration; 700 nsecs_t idleDuration = mIdleDuration; 701 mSyncDelayDuration = 0; 702 mIdleDuration = 0; 703 704 705 #if (defined OPLUS_CACHE_MISS_TRACKER) || (defined OPLUS_FEATURE_JANK_TRACKER) 706 // chengqingdong, 2024/04/24, Add for alm#7427459 707 skgpu::OplusSkStatisManager::getInstance().reset(); 708 #endif // OPLUS_CACHE_MISS_TRACKER 709 710 const auto skippedFrameReason = [&]() -> std::optional<SkippedFrameReason> { 711 #ifdef OPLUS_ARCH_EXTENDS 712 //caoyang@MULTIMEDIA.DISPLAY.GPU, 2024/5/30, add for fault inject 713 if (!isDrawingEnabled()) { 714 #else 715 if (!Properties::isDrawingEnabled()) { 716 #endif /*OPLUS_ARCH_EXTENDS*/ 717 return SkippedFrameReason::DrawingOff; 718 } 719 720 if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) { 721 return SkippedFrameReason::NothingToDraw; 722 } 723 724 return std::nullopt; 725 }(); 726 if (skippedFrameReason) { 727 mCurrentFrameInfo->setSkippedFrameReason(*skippedFrameReason); 728 729 #ifdef __ANDROID__ 730 if (auto grContext = getGrContext()) { 731 // Submit to ensure that any texture uploads complete and Skia can 732 // free its staging buffers. 733 grContext->flushAndSubmit(); 734 } 735 #endif 736 737 // Notify the callbacks, even if there's nothing to draw so they aren't waiting 738 // indefinitely 739 waitOnFences(); 740 for (auto& func : mFrameCommitCallbacks) { 741 std::invoke(func, false /* didProduceBuffer */); 742 } 743 mFrameCommitCallbacks.clear(); 744 #ifdef OPLUS_FEATURE_JANK_TRACKER 745 mTextureInfo.clear(); 746 #endif /* OPLUS_FEATURE_JANK_TRACKER */ 747 #ifdef OPLUS_BUG_STABILITY 748 //liudehua@MULTIMEDIA.DISPLAY.HWUI, 2022/11/01, print log when dirty is empty 749 ATRACE_NAME("DirtyIsEmpty"); 750 #endif /* OPLUS_BUG_STABILITY */ 751 #ifdef OPLUS_FEATURE_THEIA 752 //caoyang@MULTIMEDIA.DISPLAY.GPU, 2024/5/7, add for renderthreadNoDraw 753 mDirtyDuration = systemTime(SYSTEM_TIME_MONOTONIC) - mDirtyCheckTime; 754 mDirtyFrameCount++; 755 #endif /*OPLUS_FEATURE_THEIA*/ 756 return; 757 } 758 #ifdef OPLUS_FEATURE_THEIA 759 //caoyang@MULTIMEDIA.DISPLAY.GPU, 2024/5/7, add for renderthreadNoDraw 760 if (mDirtyFrameCount > MIN_DIRTY_FRAME_COUNT) { 761 ALOGE("DirtyFrameCount reached %d", mDirtyFrameCount); 762 mCanvasContextExt->reportTheiaEvents(mDirtyDuration, SkipFrameReason::DIRTY_IS_EMPTY, mPackageName); 763 } 764 mDirtyCheckTime = systemTime(SYSTEM_TIME_MONOTONIC); 765 mDirtyDuration = 0; 766 mDirtyFrameCount = 0; 767 #endif /*OPLUS_FEATURE_THEIA*/ 768 769 ScopedActiveContext activeContext(this); 770 mCurrentFrameInfo->set(FrameInfoIndex::FrameInterval) = 771 mRenderThread.timeLord().frameIntervalNanos(); 772 773 mCurrentFrameInfo->markIssueDrawCommandsStart(); 774 775 #ifdef OPLUS_BUG_STABILITY 776 // add for bug fix:2767817 777 // It will cause a crash, if mEglSurface is EGL_NO_SURFACE 778 if (!mRenderPipeline->isSurfaceReady()) { 779 //ZhangLijun@MULTIMEDIA.DISPLAY.HWUI, 2023/01/07, print log when destroy 780 ALOGE("mEglSurface == EGL_NO_SURFACE:this=%p, mRenderPipeline=%p", this, mRenderPipeline.get()); 781 } 782 #endif /* OPLUS_BUG_STABILITY */ 783 784 Frame frame = getFrame(); 785 786 SkRect windowDirty = computeDirtyRect(frame, &dirty); 787 788 ATRACE_FORMAT("Drawing " RECT_STRING, SK_RECT_ARGS(dirty)); 789 790 IRenderPipeline::DrawResult drawResult; 791 { 792 // FrameInfoVisualizer accesses the frame events, which cannot be mutated mid-draw 793 // or it can lead to memory corruption. 794 drawResult = mRenderPipeline->draw( 795 frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue, mContentDrawBounds, 796 mOpaque, mLightInfo, mRenderNodes, &(profiler()), mBufferParams, profilerLock()); 797 } 798 799 uint64_t frameCompleteNr = getFrameNumber(); 800 801 waitOnFences(); 802 803 if (mNativeSurface) { 804 // TODO(b/165985262): measure performance impact 805 const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId); 806 if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) { 807 const auto inputEventId = 808 static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId)); 809 const ANativeWindowFrameTimelineInfo ftl = { 810 .frameNumber = frameCompleteNr, 811 .frameTimelineVsyncId = vsyncId, 812 .inputEventId = inputEventId, 813 .startTimeNanos = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime), 814 .useForRefreshRateSelection = solelyTextureViewUpdates, 815 .skippedFrameVsyncId = mSkippedFrameInfo ? mSkippedFrameInfo->vsyncId 816 : UiFrameInfoBuilder::INVALID_VSYNC_ID, 817 .skippedFrameStartTimeNanos = 818 mSkippedFrameInfo ? mSkippedFrameInfo->startTime : 0, 819 }; 820 native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), ftl); 821 } 822 } 823 824 bool requireSwap = false; 825 bool didDraw = false; 826 827 int error = OK; 828 bool didSwap = mRenderPipeline->swapBuffers(frame, drawResult, windowDirty, mCurrentFrameInfo, 829 &requireSwap); 830 831 mCurrentFrameInfo->set(FrameInfoIndex::CommandSubmissionCompleted) = std::max( 832 drawResult.commandSubmissionTime, mCurrentFrameInfo->get(FrameInfoIndex::SwapBuffers)); 833 834 mIsDirty = false; 835 836 if (requireSwap) { 837 didDraw = true; 838 // Handle any swapchain errors 839 error = mNativeSurface->getAndClearError(); 840 if (error == TIMED_OUT) { 841 // Try again 842 mRenderThread.postFrameCallback(this); 843 // But since this frame didn't happen, we need to mark full damage in the swap 844 // history 845 didDraw = false; 846 847 } else if (error != OK || !didSwap) { 848 // Unknown error, abandon the surface 849 setSurface(nullptr); 850 didDraw = false; 851 } 852 853 SwapHistory& swap = mSwapHistory.next(); 854 if (didDraw) { 855 swap.damage = windowDirty; 856 } else { 857 float max = static_cast<float>(INT_MAX); 858 swap.damage = SkRect::MakeWH(max, max); 859 } 860 swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC); 861 swap.vsyncTime = mRenderThread.timeLord().latestVsync(); 862 if (didDraw) { 863 nsecs_t dequeueStart = 864 ANativeWindow_getLastDequeueStartTime(mNativeSurface->getNativeWindow()); 865 if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) { 866 // Ignoring dequeue duration as it happened prior to frame render start 867 // and thus is not part of the frame. 868 swap.dequeueDuration = 0; 869 } else { 870 swap.dequeueDuration = 871 ANativeWindow_getLastDequeueDuration(mNativeSurface->getNativeWindow()); 872 } 873 swap.queueDuration = 874 ANativeWindow_getLastQueueDuration(mNativeSurface->getNativeWindow()); 875 } else { 876 swap.dequeueDuration = 0; 877 swap.queueDuration = 0; 878 } 879 mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = swap.dequeueDuration; 880 mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = swap.queueDuration; 881 mHaveNewSurface = false; 882 mFrameNumber = 0; 883 } else { 884 mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = 0; 885 mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = 0; 886 } 887 888 #ifdef OPLUS_FEATURE_JANK_TRACKER 889 //wangwei11@oppo.com, 2021/11/28, Add for janktracker 890 if (mHasFunctor) { 891 //Mark webview scene 892 set(OpFrameInfoIndex::Flags) |= (1 << 13); 893 } 894 set(OpFrameInfoIndex::MuTableImageSize) = static_cast<int>(mRenderPipeline->getPinnedImageSize()); 895 set(OpFrameInfoIndex::LayerRenderTime) = mRenderPipeline->getLayerRenderTime(); 896 set(OpFrameInfoIndex::FrameRenderTime) = mRenderPipeline->getRenderFrameTime(); 897 set(OpFrameInfoIndex::WaitOnFencesTime) = mWaitOnFencesCost; 898 set(OpFrameInfoIndex::TextureUploadTimes) = skgpu::OplusSkStatisManager::getInstance().getTextureUploadSum(); 899 set(OpFrameInfoIndex::CacheMissTimes) = skgpu::OplusSkStatisManager::getInstance().getCacheMissSize(); 900 mWaitOnFencesCost = 0; 901 mCurrentFrameInfo->syncOpFrameInfo(mOpFrameInfo); 902 mCurrentFrameInfo->syncTextureInfo(mTextureInfo); 903 #endif /* OPLUS_FEATURE_JANK_TRACKER */ 904 mCurrentFrameInfo->markSwapBuffersCompleted(); 905 906 #if LOG_FRAMETIME_MMA 907 float thisFrame = mCurrentFrameInfo->duration(FrameInfoIndex::IssueDrawCommandsStart, 908 FrameInfoIndex::FrameCompleted) / 909 NANOS_PER_MILLIS_F; 910 if (sFrameCount) { 911 sBenchMma = ((9 * sBenchMma) + thisFrame) / 10; 912 } else { 913 sBenchMma = thisFrame; 914 } 915 if (++sFrameCount == 10) { 916 sFrameCount = 1; 917 ALOGD("Average frame time: %.4f", sBenchMma); 918 } 919 #endif 920 921 if (didSwap) { 922 for (auto& func : mFrameCommitCallbacks) { 923 std::invoke(func, true /* didProduceBuffer */); 924 } 925 mFrameCommitCallbacks.clear(); 926 } 927 928 if (requireSwap) { 929 #ifdef OPLUS_FEATURE_JANK_TRACKER 930 //wangwei11@oppo.com, 2021/11/28, Add for janktracker 931 if (CC_UNLIKELY(Properties::debugLevel & 4)) { 932 mExpectSurfaceStats = false; // add for debug 933 } 934 #endif /* OPLUS_FEATURE_JANK_TRACKER */ 935 if (mExpectSurfaceStats) { 936 reportMetricsWithPresentTime(); 937 { // acquire lock 938 std::lock_guard lock(mLast4FrameMetricsInfosMutex); 939 FrameMetricsInfo& next = mLast4FrameMetricsInfos.next(); 940 next.frameInfo = mCurrentFrameInfo; 941 next.frameNumber = frameCompleteNr; 942 next.surfaceId = mSurfaceControlGenerationId; 943 } // release lock 944 } else { 945 mCurrentFrameInfo->markFrameCompleted(); 946 mCurrentFrameInfo->set(FrameInfoIndex::GpuCompleted) 947 = mCurrentFrameInfo->get(FrameInfoIndex::FrameCompleted); 948 std::scoped_lock lock(mFrameInfoMutex); 949 mJankTracker.finishFrame(*mCurrentFrameInfo, mFrameMetricsReporter, frameCompleteNr, 950 mSurfaceControlGenerationId); 951 } 952 #ifdef OPLUS_FEATURE_JANK_TRACKER 953 //wangwei11@oppo.com, 2022/12/2, Add for janktracker 954 mJankTracker.mJankTrackerExt->finishFrame(*mCurrentFrameInfo); 955 #endif /* OPLUS_FEATURE_JANK_TRACKER */ 956 } 957 958 int64_t intendedVsync = mCurrentFrameInfo->get(FrameInfoIndex::IntendedVsync); 959 int64_t frameDeadline = mCurrentFrameInfo->get(FrameInfoIndex::FrameDeadline); 960 int64_t dequeueBufferDuration = mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration); 961 962 mHintSessionWrapper->updateTargetWorkDuration(frameDeadline - intendedVsync); 963 964 if (didDraw) { 965 int64_t frameStartTime = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime); 966 int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime; 967 int64_t actualDuration = frameDuration - 968 (std::min(syncDelayDuration, mLastDequeueBufferDuration)) - 969 dequeueBufferDuration - idleDuration; 970 mHintSessionWrapper->reportActualWorkDuration(actualDuration); 971 mHintSessionWrapper->setActiveFunctorThreads( 972 WebViewFunctorManager::instance().getRenderingThreadsForActiveFunctors()); 973 } 974 975 mLastDequeueBufferDuration = dequeueBufferDuration; 976 977 mRenderThread.cacheManager().onFrameCompleted(); 978 return; 979 }完整代码在此,作用是在buffer上进行绘制吗,从哪里体现的
最新发布
08-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值