[C++/CLI]Private var wordt in eigen klasse niet herkend *

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
Ik ben bezig met een avondcursus HBO TI, nu zijn we net begonnen met C++(.net) en over het algemeen lukt het vrij aardig, echter loop ik nu een beetje vast.

Ik heb een klasse TuneGenerator, die heeft de volgende header file.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
using namespace Microsoft::DirectX::DirectSound;
using namespace System; //Nodig om Math te kunnen gebruiken.

public ref class TuneGenerator{
    public:
        TuneGenerator(WaveFormat waveFormat); //Constructor
        void geneerToon(); //Genereert een PiepToon
        void geneerDoom(); //Genereert een DoomToon
        array<unsigned char> ^getBuffer();
    private:
        array <unsigned char> ^mixBuffer;  //Array die de Buffer bevat.
        WaveFormat waveFormat; //Beschrijft de "wave file"


De constructor in de CPP file ziet er als volgt uit.

C++:
1
2
3
4
5
6
7
8
9
10
11
TuneGenerator::TuneGenerator(WaveFormat wFormat){
    //Constructor
     
    //Stel waveformat in, om de tonen juist te kunnen genereren.
    waveFormat = wFormat;
    Console::WriteLine("Samples per second: "+waveFormat.SamplesPerSecond); //Debug
    //waveFormat.SamplesPerSecond=22050;

    //Vul de array
    mixBuffer = gcnew array <unsigned char> (waveFormat.SamplesPerSecond);
};


Vanuit een andere klasse wordt de waveFormat gedefinieerd, en wordt er een object aangemaakt van de TuneGenerator, waar de waveFormat aan meegegeven wordt. Nu zou naar mijn inziens waveFormat bekend moeten zijn binnen het aangemaakte object TuneGenerator, in de constructor, schrijft deze ook netjes naar de console de waarde "22050".

Echter nu wordt er vanuit mijn TuneBeheer een methode aangeroepen in de klasse TuneGenerator.

C++:
1
2
3
4
5
6
7
8
9
10
void TuneGenerator::geneerToon(){
    int intVolume = 100;
    int intFrequentie = 2000;

    Console::WriteLine("Samples per second: "+this->waveFormat.SamplesPerSecond);
    for(int i=0;i< waveFormat.SamplesPerSecond-1;i++){
        mixBuffer[i]=(unsigned char)
            (intVolume*Math::Sin((double(i*2*Math::PI*intFrequentie/(waveFormat.SamplesPerSecond)))));
    }
};


Echter tijdens het draaien klapt deze er hier uit met een "System.NullReferenceException" error. m.b.v. een breakpoint, kwam ik erachter dat het gebeurde op this->waveFormat.SamplesPerSecond.
Als ik tijdens het debuggen ook de waveFormat controleer, staat er ook idd achter SamplesPerSecond, "error: cannot obtain value".

Iemand die mij hier wat licht in de duisternis kan brengen, waardoor de waarde van de waveFormat niet netjes doorgegeven worden?

If it is broken, fix it. If it ain't broken, make it better!


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:19
dit duidt gewoon dat je ergens naar een variable verwijst die niet gealloceerd is. Hoe creeër je een instance van die class ? Je geeft wel degelijk een WaveFormat mee ?
Hoe wordt die waveFormat gecreeërd / gedefinieerd, en geeft SamplesPerSecond wel een waarde ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
whoami schreef op vrijdag 02 maart 2007 @ 11:52:
dit duidt gewoon dat je ergens naar een variable verwijst die niet gealloceerd is. Hoe creeër je een instance van die class ? Je geeft wel degelijk een WaveFormat mee ?
Hoe wordt die waveFormat gecreeërd / gedefinieerd, en geeft SamplesPerSecond wel een waarde ?
In de constructor van de TuneBeheer klasse, staat dit.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TuneBeheer::TuneBeheer(Device ^sound){
    //SoundDevice toekennen
    devSound = sound;

    //WaveFormat instellen
    waveFormat.FormatTag = WaveFormatTag::Pcm;
    waveFormat.SamplesPerSecond=22050;
    waveFormat.BitsPerSample=16;
    waveFormat.Channels=1;
    waveFormat.BlockAlign=(short)(waveFormat.Channels * (waveFormat.BitsPerSample/8));
    waveFormat.AverageBytesPerSecond= waveFormat.SamplesPerSecond*waveFormat.BlockAlign; 
    
    //Bufferdescriptie instellen
    bufferDescription= gcnew BufferDescription(waveFormat);
    bufferDescription->BufferBytes=waveFormat.AverageBytesPerSecond;
    
    //Buffer instellen
    tuneBuffer = gcnew SecondaryBuffer(bufferDescription, devSound);
    
    //TuneGenerator aanmaken
    TuneGenerator ^objTuneGenerator = gcnew TuneGenerator(waveFormat); //Maak een object TuneGenerator aan.
};


Onderaan wordt de TuneGenerator aangemaakt, met de waveFormat die daarboven is gedefinieerd.
Het gekke is ook dat op het moment dat de constructor van de tunegenerator wordt uitgevoerd, de waarde netjes op het console geprint wordt. 8)7

If it is broken, fix it. If it ain't broken, make it better!


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:19
En tussen het creeëren van je tune-generator en het aanroepen van die bewuste method wordt die waveFormat nergens op null gezet ofzo ?
Heb je al eens stap voor stap door je code gelopen ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
Ik heb de code inderdaad al een keer stap voor stap doorlopen, maar alle code die ook maar iets doet met waveFormat staat hier.

Na de initialisatie wordt ook direct genereerToon aangeropen.

If it is broken, fix it. If it ain't broken, make it better!


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
whoami schreef op vrijdag 02 maart 2007 @ 12:05:
En tussen het creeëren van je tune-generator en het aanroepen van die bewuste method wordt die waveFormat nergens op null gezet ofzo ?
Heb je al eens stap voor stap door je code gelopen ?
Hmm, het lijkt erop dat er inderdaad wel iets mee gebeurd, als ik onder de regel, waar ik objTuneGenerator aanmaak, de genereertoon aanroep, gaat het wel goed.

Maar als ik hem direct daarna vanuit een andere methode aanroep gaat het mis, ik ga even verder puzzelen.

If it is broken, fix it. If it ain't broken, make it better!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:28

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op vrijdag 02 maart 2007 @ 12:05:
En tussen het creeëren van je tune-generator en het aanroepen van die bewuste method wordt die waveFormat nergens op null gezet ofzo ?
Heb je al eens stap voor stap door je code gelopen ?
waveFormat kan niet op null worden gezet - het is immers geen (managed) pointer. Wat ik me echter afvraag is waar je de referentie naar de instance van je TuneGenerator opslaat. Want in TuneBeheer::TuneBeheer is dit een lokale variabele. Mijn gok is dus dat je ergens anders tuneGen->genereerToon() aanroept, terwijl tuneGen null is.

Dat verklaart ook die NullReferenceException - this is null in genereerToon().

.edit: deze taal heet trouwens C++/CLI, niet C++ ;)

[ Voor 8% gewijzigd door .oisyn op 02-03-2007 13:02 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
Het verhaal klinkt logisch en het lijkt er inderdaad op dat het zoiets dergelijks is, maar volgens mij sla ik het goed op, althans ik kan het niet vinden.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "TuneGenerator.h"

using namespace Microsoft::DirectX;
using namespace Microsoft::DirectX::DirectSound;
using namespace System;
using namespace System::IO;

public ref class TuneBeheer{
    public:
        TuneBeheer(Device ^sound);
        //void speelToon(String ^toon);
        void speelToon();
    private:
        Device ^devSound;
        SecondaryBuffer ^tuneBuffer;
        BufferDescription ^bufferDescription;
        TuneGenerator ^objTuneGenerator;
        array <unsigned char> ^mixBuffer; 
        WaveFormat waveFormat;
        MemoryStream ^mStream;
};


En in de CPP van TuneBeheer, staat ook deze methode, die de methode genereertoon aanroept.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
void TuneBeheer::speelToon(){
    //Afspelen van de toon
    //Toon kiezen
    objTuneGenerator->geneerToon();

    //Buffer vullen
    mixBuffer = objTuneGenerator->getBuffer();

    mStream = gcnew MemoryStream(mixBuffer);
    tuneBuffer->Write(0,mStream,tuneBuffer->Caps.BufferBytes,LockFlag::None);
    tuneBuffer->Play(0,BufferPlayFlags::Default);
}


Het gaat dus mis bij de eerste regel van deze methode.
Deze methode, wordt wel aangeroepen vanuit een andere klasse, de complete werking is als volgt.

TuneMaker klasse -> in de constructor wordt een TuneBeheer object aangemaakt.
TuneBeheer object wordt aangemaakt vanuit TuneMaker en maakt een TuneGenerator object

Vanuit het object TuneMaker, wordt de functie speelToon in TuneBeheer aangeroepen.

Hieronder nog de TuneMaker.cpp (wel wat form-opmaak code weggehaald).
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// TuneMaker.cpp : main project file.
#include "stdafx.h"
#include "TuneBeheer.h"

#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace Microsoft::DirectX;
using namespace Microsoft::DirectX::DirectSound;
using namespace System; 
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;

public ref class TuneMaker:public Form{
    private:
<KNIP>
        
        //Overige objecten
        Device ^devSound; //Sound device, legt de link tussen de applicatie en de geluidskaart
        SecondaryBuffer ^buffer; //Buffer bevat het af te spelen te bestand.

        //TuneBeheer object
        TuneBeheer ^objTuneBeheer;

<KNIP>
    public:
        TuneMaker(){
            //Declaraties en initialisatie
            devSound = gcnew Device();
            //Zorgt ervoor dat de kaart samenwerkt met andere programma's
            devSound->SetCooperativeLevel(this, CooperativeLevel::Normal); 
            //Buffer declaren, anders kan het volume niet meteen ingesteld worden
            buffer= gcnew SecondaryBuffer("test.wav",devSound);

            //Object TuneBeheer aanmaken                    
            objTuneBeheer = gcnew TuneBeheer(devSound);


            //Bouw het scherm op
            Setup_Form();
        };
};


int main(void)
{   
    Console::WriteLine("TuneMaker Form");
    
    //Creeër een formulier
    Application::Run(gcnew TuneMaker());
    return 0;
}

If it is broken, fix it. If it ain't broken, make it better!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:28

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, je slaat het niet goed op:
BlackBurn schreef op vrijdag 02 maart 2007 @ 11:59:

In de constructor van de TuneBeheer klasse, staat dit.
C++:
1
2
3
4
5
6
TuneBeheer::TuneBeheer(Device ^sound){
    // ....

    //TuneGenerator aanmaken
    TuneGenerator ^objTuneGenerator = gcnew TuneGenerator(waveFormat); //Maak een object TuneGenerator aan.
};
Je definieert hier een lokale variabele objTuneGenerator. Je slaat 'm niet op in this->objTuneGenerator.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • BlackBurn
  • Registratie: Juni 2001
  • Laatst online: 13-09 19:26

BlackBurn

One Ring To Rule Them All

Topicstarter
.oisyn schreef op vrijdag 02 maart 2007 @ 14:25:
Nee, je slaat het niet goed op:


[...]

Je definieert hier een lokale variabele objTuneGenerator. Je slaat 'm niet op in this->objTuneGenerator.
Dat was inderdaad de oplossing _/-\o_

Dat ik daar zolang naar moest zoeken :| Harstikke bedankt!

If it is broken, fix it. If it ain't broken, make it better!

Pagina: 1