Hi Luke, I've had this issue before.
The problem is that the Function Probe block is not actually a block, it's just a way to write code directly into the top_block python file, and do the top_block object is the one calling the block you want, which is not an issue since, it knows them, it created them.
Now, whatever block you create doesn't have reference to the other blocks, and I could not find a way to give it to them directly, so what I found is to give the top_block object to yours, and also the name of the block(s) you want, and call them with getattr(top_block_object, wanted_block_name).whatever_function() . It needs to be the name used for the exact block you want, not the type, you can find it in the id field in the parameters, or by reading the top_block file.
The other issue is the fact that, with an embedded block, when you save it, GRC creates an instance of the object automatically with the default parameters, possibly to find out its signature and be able to display it properly. But, at that point, the top block object doesn't exist, so the execution will stop and GRC will complain.
If you work with an OOT python block, you won't have this issue, but if you really want to stick with embedded, I've done that too:
If the constructor is not the function that gets the top_block as input, but another function (not called in the init phase), you can have it be called by a function probe (the frequency doesn't need to be high) and put "self" as argument. Then you can use it to call whatever in your function, or even store it in your block object for later use.
This is really hacky, and there may be a better way to do it but I couldn't find at the time, and it works without issue.
Tell me if this was not clear, or if you need example code. Cyrille Le 21/02/2020 à 00:24, Lukas Haase a écrit :
Hi, I am using the "Embedded Python Block" to create a simple controller that controls my USRP Source/Sink blocks. These blocks support a message interface but unfortunately this is pretty useless except for the simplest applications (I need to control advanced tuning with timed commands, GPIO ports etc). Hence I need to call the methods of these objects directly but I need a reference to them inside my custom block. Within my python block I cannot reference the parent blocks, hence I need to pass a reference to these two objects via the constructor (and parameters). Basically I want to do the same as parameter "Block ID" from the block "Function Probe" does. What is the best way to implement this? Thanks, Luke PS: Example: class blk(gr.sync_block): # other base classes are basic_block, decim_block, interp_block def __init__(self, sample_rate=1.0, usrp_source_block=''): # only default arguments here """arguments to this function show up as parameters in GRC""" gr.sync_block.__init__( self, name='Controller', # will show up in GRC in_sig=[np.float32], out_sig=[np.float32] ) # if an attribute with the same name as a parameter is found, # a callback is registered (properties work, too). self.sample_rate = sample_rate self.usrp_source_block = usrp_source_block # here I want to execute for example self.usrp_source_block.set_gain(5.0) When I then create an USRP Sink object with ID uhd_usrp_sink_0 and enter as parameter I get the error: Param - Usrp Source Block(usrp_source_block): Value "uhd_usrp_sink_0" cannot be evaluated: name 'uhd_usrp_sink_0' is not defined