मैं एक प्रबंधित फ़ंक्शन के साथ एक पॉइंटर को परिभाषित करता हूं:

typedef void(__stdcall* CounterCallback)(int count);

तो मैं एक सी ++ विधि परिभाषित करूंगा:

void CBSpline::GenFlowcache(/*few irrelevant parameters*/, CounterCallback func)
{/*instructions*/}

और एक इकाई परीक्षण में, मैं एक मूल कार्य के साथ GenFlowcache का परीक्षण करना चाहता हूं।

int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }

TEST_METHOD(Gen_CallbackTest)
{
    // ...
    sut.GenFlowcache(/**/, static_cast<CounterCallback>(GenFlowcacheTests::Increment));
}

लेकिन मुझे विधि डालने का कोई तरीका नहीं मिल रहा है:

static_cast के माध्यम से 'शून्य (GenFlowcacheTests::*)(int)' से 'void(*)(int)' तक नहीं डाला जा सकता

(संकलक त्रुटि C2440)

मैं एक नेटिव फंक्शन (विधि, लैम्ब्डा आदि) को CounterCallback के रूप में कैसे पास कर सकता हूं?

यह समस्या के लिए उपयोगी नहीं है, लेकिन प्रबंधित हिस्सा इस प्रकार है:

public delegate void CounterCallback(int value);

public static class CBSplines
{
    [DllImport("CubicBSplines.dll", CallingConvention = CallingConvention.StdCall)]
    internal static extern unsafe void GenFlowcache(IntPtr p, BroxParam* broxParam, IntPtr sourceDir, IntPtr targetDir, CounterCallback counter);
}

फिर एक प्रबंधित वर्ग में:

private CounterCallback _counter;

public unsafe void GenerateFlowcache(BroxParam parameters, string sourceDir, string targetLocalDir)
{
    if (_counter is null)
        _counter = CounterUpdated;
    if (!Directory.Exists(targetLocalDir))
        Directory.CreateDirectory(targetLocalDir);
    var strSrcDir = Marshal.StringToHGlobalAuto(sourceDir);
    var strTgtDir = Marshal.StringToHGlobalAuto(targetLocalDir);
    CBSplines.GenFlowcache(_ptr, &parameters, strSrcDir, strTgtDir, _counter);
    Marshal.FreeHGlobal(strSrcDir);
    Marshal.FreeHGlobal(strTgtDir);
}

protected void CounterUpdated(int value) => FlowcacheCounter = value;

और वापस देशी में:

#ifndef Pinvoke
#define Pinvoke extern "C" __declspec(dllexport)
#endif

Pinvoke auto GenFlowcache(CBSpline* p, BroxParam* param, const wchar_t* sourceDir, const wchar_t* targetDir, CounterCallback func)
-> void { p->GenFlowcache(param, sourceDir, targetDir, func); }
1
Soleil 1 जिंदा 2021, 22:50
4
आप कुछ भी याद नहीं कर रहे हैं, आप एक गैर स्थैतिक वर्ग विधि को फ़ंक्शन पॉइंटर में नहीं डाल सकते हैं।
 – 
john
1 जिंदा 2021, 22:52
3
इस सब में C# कहाँ है? मैं यहाँ C# के लिए आया हूँ, इसलिए मुझे C# चाहिए
 – 
xanatos
1 जिंदा 2021, 23:01
2
@ Soleil-MathieuPrévot आप void(int) टाइप किया गया फ़ंक्शन या स्थिर विधि पास कर सकते हैं, आप उसी हस्ताक्षर के साथ एक गैर-कैप्चरिंग लैम्ब्डा भी पास कर सकते हैं, और बस। आप क्लास विधि पास नहीं कर सकते हैं हालांकि यह टाइप किया गया है।
 – 
john
1 जिंदा 2021, 23:03
1
@ Soleil-MathieuPrévot आपके पास C ++ में एक उदाहरण के लिए एक पॉइंटर हो सकता है, यह सिर्फ इतना है कि यह किसी फ़ंक्शन के पॉइंटर के साथ संगत नहीं है। मुझे सी # के बारे में पता नहीं है, शायद यह पर्दे के पीछे कुछ जादू कर रहा है। आप स्पष्ट रूप से सी ++ में वही जादू कर सकते हैं लेकिन केवल तभी जब आपका लक्ष्य सही हो। यह मुझे लगता है कि मौलिक समस्या है, आप जो हासिल करने की कोशिश कर रहे हैं उसके लिए आपका CounterCallback प्रकार गलत है। शुद्ध C++ में हम या तो एक टेम्प्लेट या std::function का उपयोग करेंगे, ये दोनों फ़ंक्शन पॉइंटर्स और सदस्य पॉइंटर्स दोनों के साथ काम कर सकते हैं।
 – 
john
2 जिंदा 2021, 10:00
1
@ Soleil-MathieuPrévot C# में Delegate (जिसे आप इंस्टेंस मेथड के लिए पॉइंटर कहते हैं) ऑब्जेक्ट दो भागों से बना होता है: मेथड के लिए एक पॉइंटर और एक "टारगेट" (उपयुक्त नाम Target) जो कि वस्तु का उदाहरण है (या स्थिर विधियों के लिए null)। आप इसे var c = new List<int>(); Action<int> a = c.Add; bool eq = c == a.Target; से जांच सकते हैं
 – 
xanatos
2 जिंदा 2021, 11:35

1 उत्तर

सबसे बढ़िया उत्तर

जैसा कि जॉन ने बताया:

आप void(int) टाइप किए गए फ़ंक्शन या स्थिर विधि को पास कर सकते हैं, आप उसी हस्ताक्षर के साथ एक गैर-कैप्चरिंग लैम्ब्डा भी पास कर सकते हैं, और बस। आप क्लास मेथड पास नहीं कर सकते, हालांकि यह टाइप किया गया है

मैं एक वैश्विक कार्य पास कर सकता हूं:

int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }

जो परीक्षण विधि में पारित किया जाएगा:

sut.GenFlowcache(/**/, (CounterCallback)Increment);
0
Soleil 2 जिंदा 2021, 05:00