小编Pet*_*man的帖子

在C中if(function()== TRUE)的任何原因

问题: 是否做了if(SomeFunction() == TRUE)而不是做if(SomeFunction())某些类型的编码错误?我试图了解这是否可以防止某些隐藏的地雷,或者是否是某人编写代码并且不太明白如何评估表达式的结果.我明白,如果做得对,这两件事情的评价都是一样的.就像if(value == 42)if(42 == value)评估相同 - 仍然,有些人更喜欢第二个版本,因为如果有人输错了==并且写入=而产生编译器错误.

背景: 我继承了一些4年或5年前由不在这里工作的人写的嵌入式软件.我正在进行一些重构以摆脱数百行函数和全局变量以及所有爵士乐,所以这个东西是可读的,我们可以继续保持它.代码是c用于pic微处理器.这可能相关也可能不相关.该代码有各种在它的尖叫奇怪的东西"不知道他们在做什么",但在这里我想了解是不是有一个很好的理由一个特定的模式(反模式?)

模式: 这里有很多if语句采用的形式

if(SomeFunction() == TRUE){
  . . .
}
Run Code Online (Sandbox Code Playgroud)

其中SomeFunction()定义为

BOOLEAN SomeFunction(void){
  . . .
  if(value == 3)
    return(FALSE);
  else
    return(TRUE);
}
Run Code Online (Sandbox Code Playgroud)

让我们忽略SomeFunction从if语句的主体返回TRUE或FALSE的奇怪方式,以及他们使'return'看起来像函数调用的奇怪方式.

这似乎打破了c认为'true'和'false'的正常值.就像,他们真的想确保返回的值等于任何被定义为TRUE的值.这几乎就像他们正在制作三种状态 - TRUE,FALSE和'其他'而且他们不希望在返回"其他东西"的情况下采用'if'语句.

我的直觉是,这是一种奇怪的反模式,但我想给这些家伙带来怀疑的好处.例如,我认识到if(31 == variable)看起来有点奇怪,但它是这样编写的,所以如果你输错了==你不会意外地将31分配给变量.如果这些人写了这个保护措施来防范类似的问题,或者这只是胡说八道.

附加信息

  • 当我写这个问题时,我的印象是stdbool不可用,但我现在看到它是由IDE提供的,只是在这个项目中没有使用过.这使我更倾向于"没有充分理由这样做".
  • 看起来BOOLEAN被定义为 typedef enum _BOOLEAN { FALSE = 0, TRUE } BOOLEAN;
  • 这里讨论的开发环境是MPLAB 8.6

c embedded microchip mplab

9
推荐指数
1
解决办法
3005
查看次数

如何以与inspect.signature配合使用的方式包装python函数?

前面一些没有争议的背景实验:

import inspect

def func(foo, bar):
  pass

print(inspect.signature(func))  # Prints "(foo, bar)" like you'd expect

def decorator(fn):
  def _wrapper(baz, *args, *kwargs):
    fn(*args, **kwargs)

  return _wrapper

wrapped = decorator(func)
print(inspect.signature(wrapped))  # Prints "(baz, *args, **kwargs)" which is totally understandable
Run Code Online (Sandbox Code Playgroud)

问题

如何实现我的装饰器以便print(inspect.signature(wrapped))吐出“(baz, foo, bar)”?我可以通过添加传入的_wrapper参数然后粘贴到列表来动态构建吗?fnbaz

答案不是

def decorator(fn):
  @functools.wraps(fn)
  def _wrapper(baz, *args, *kwargs):
    fn(*args, **kwargs)

  return _wrapper
Run Code Online (Sandbox Code Playgroud)

再次给出“(foo, bar)”——这是完全错误的。调用wrapped(foo=1, bar=2)是一个类型错误 - “缺少 1 个必需的位置参数:'baz'”

我认为没有必要如此迂腐,但是

def decorator(fn):
  def _wrapper(baz, foo, bar):
    fn(foo=foo, bar=bar)

  return _wrapper …
Run Code Online (Sandbox Code Playgroud)

python python-decorators

7
推荐指数
1
解决办法
501
查看次数

托管C++程序集可以将对象返回给C#吗?

我正在编写一个必须读取视频文件视频属性的C#应用​​程序.我发现这样做的唯一方法是使用需要C++的Microsoft Media Foundation.

到目前为止,我已经取得了一些进展:

  • 我已经创建了一个托管的C++程序集,它可以编译成DLL.
  • 我可以使用C#代码中的参数调用它.
  • 它执行并打印视频文件属性.

我接下来要做的是让DLL返回视频属性的对象(宽度,高度,持续时间等).鉴于我正在使用C++托管代码,是否有一种简单的方法来定义对象类型并使用它在C#和C++之间传递数据或者我是否必须使用Marshal类?

c# managed-c++ c++-cli

5
推荐指数
1
解决办法
2251
查看次数

线程防止所有者的垃圾收集

在我创建的库中,我有一个类DataPort,它实现类似于.NET SerialPort类的功能.它与某些硬件进行通信,并且只要数据通过该硬件进入就会引发事件.为了实现此行为,DataPort会旋转一个预期与DataPort对象具有相同生命周期的线程. 问题是当DataPort超出范围时,它永远不会被垃圾收集

现在,因为DataPort与硬件(使用pInvoke)对话并拥有一些非托管资源,所以它实现了IDisposable.当您在对象上调用Dispose时,一切都正常.DataPort摆脱了所有非托管资源并杀死了工作线程并消失了.但是,如果只是让DataPort超出范围,垃圾收集器将永远不会调用终结器,并且DataPort将永远保留在内存中.我知道这种情况有两个原因:

  1. 终结者中的断点永远不会被击中
  2. SOS.dll告诉我DataPort仍然存在

补充:在我们再进一步之前,我会说是的,我知道答案是"Call Dispose()Dummy!" 但我认为,即使你让所有引用超出范围,最终应该发生正确的事情,垃圾收集器应该摆脱DataPort

回到问题:使用SOS.dll,我可以看到我的DataPort没有被垃圾回收的原因是因为它旋转的线程仍然具有对DataPort对象的引用 - 通过隐含的"this"参数线程正在运行的实例方法.正在运行的工作线程不会被垃圾回收,因此在正在运行的工作线程范围内的任何引用也不符合垃圾回收的条件.

线程本身基本上运行以下代码:

public void WorkerThreadMethod(object unused)
{
  ManualResetEvent dataReady = pInvoke_SubcribeToEvent(this.nativeHardwareHandle);
  for(;;)
  {
    //Wait here until we have data, or we got a signal to terminate the thread because we're being disposed
    int signalIndex = WaitHandle.WaitAny(new WaitHandle[] {this.dataReady, this.closeSignal});
    if(signalIndex == 1) //closeSignal is at index 1
    {
      //We got the close signal.  We're being disposed!
      return; //This will stop …
Run Code Online (Sandbox Code Playgroud)

c# multithreading garbage-collection memory-leaks

5
推荐指数
1
解决办法
1213
查看次数

如何通过禁用名称修改来 PInvoke 实例方法

给定 foo.dll 中的以下 c++ 类

class a{
  private:
    int _answer;

  public:
    a(int answer) { _answer = answer; }
    __declspec(dllexport) int GetAnswer() { return _answer; }
}
Run Code Online (Sandbox Code Playgroud)

我想要来自 C# 的 pInvoke GetAnswer。为此,我使用以下方法:

[DllImport("foo.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint= "something")]
public static extern int GetAnswer(IntPtr thisA);
Run Code Online (Sandbox Code Playgroud)

我传入一个指向 a 的 IntPtr(我从其他地方得到的,这并不重要)。 CallingConvention = CallingConvention.ThisCall确保正确处理

这个问题很酷的是,我知道到目前为止我是对的,因为它已经很好用了! 使用 Depends.exe,我可以看到“GetAnswer”被导出为 ?GetAnswer@a@@UAEHXZ (或者接近的东西 - 关键是它的名称被破坏了)。当我将损坏的名称插入 EntryPoint 的“某物”时,一切正常!我花了大约一天的时间才意识到使用 Depends.exe,所以我将把它留在这里作为对任何有类似问题的人的帮助。

我真正的问题是: 有什么方法可以在 GetAnswer 上禁用 C++ 名称重整,这样我就不需要将重整名称作为我的入口点。将重整名称放在那里似乎可能会中断,因为我对名称重整的理解是,如果编译器更改,它会更改。此外,对于我想要 pInvoke 的每个实例方法使用 Depends.exe 也很麻烦。

编辑:忘记添加我尝试过的内容:我似乎无法将 extern "C" 放在函数声明中,尽管我可以将其粘贴在定义上。虽然这似乎没有帮助(当你考虑它时这很明显)

我能想到的唯一其他解决方案是一个 c 风格的函数,它包装了实例方法并将 a …

c# c++ pinvoke name-mangling

5
推荐指数
1
解决办法
2007
查看次数

反转按需迭代器

我有一个DataIterator按需生成值的迭代器,因此取消引用运算符返回一个Data,而不是Data&.我认为这是一件好事,直到我试图通过将数据包装在reverse_iterator中来反转数据DataIterator.

DataCollection collection

std::reverse_iterator<DataIterator> rBegin(iter) //iter is a DataIterator that's part-way through the collection
std::reverse_iterator<DataIterator> rEnd(collection.cbegin());

auto Found = std::find_if(
    rBegin, 
    rEnd,
    [](const Data& candidate){
        return candidate.Value() == 0x00;
});
Run Code Online (Sandbox Code Playgroud)

当我运行上面的代码时,它永远不会找到一个值等于0的Data对象,即使我知道一个存在.当我在谓词中插入一个断点时,我会看到奇怪的值,我永远不会期望看到像0xCCCC - 可能是未初始化的内存.会发生什么是reverse_iterator的解引用运算符看起来像这样(来自xutility - Visual Studio 2010)

Data& operator*() const
{   // return designated value
    DataIterator _Tmp = current;
    return (*--_Tmp); //Here's the problem - the * operator on DataIterator returns a value instead of a reference
}
Run Code Online (Sandbox Code Playgroud)

最后一行是问题所在 - 创建临时数据并返回对该数据的引用.该引用立即无效.

如果我将std :: find_if中的谓词更改为(数据候选者)而不是(const数据和候选者),那么谓词就可以了 - 但我很确定我只是幸运地遇到了未定义的行为.引用无效,但我在内存被破坏之前复制数据.

我能做什么?

  1. 修复我的DataIterator,以便operator*返回Data而不是Data?我真的不明白这是怎么回事.我的DataIterator返回Data而不是Data的重点是因为我没有空间将整个未压缩的数据集保存在内存中,所以我创建了你想要按需查看的项目. …

c++ iterator stl reverse-iterator

5
推荐指数
1
解决办法
151
查看次数

在Verilog中混合分配阻塞和非阻塞分配(或不分配!)

我在Verilog中实现了一个简单的序列化程序,但我不了解何时阻止分配会导致问题的细微差别。我特别难以理解此答案的一部分。“但是,永远不要将阻塞分配用于同步通信,因为这是不确定的。”

我正在构建一个将其作为输入的块:

  • 有点钟
  • 5位并行数据输入(要序列化的值)
  • “数据有效”信号指示存在有效的5位数据

作为输出,我有:

  • 串行数据输出
  • 一个“完成”信号,指示是时候输入一个新的5位值
  • 每当总线上有有效的串行数据流出时,“发送”信号就为高

每当有效数据变高时,该块便开始从位时钟的下一个上升沿开始,一次输出5位值。当最后一位丢失时,该块发出“完成”信号,因此可以使用新的5位值。

省略一些复位逻辑,执行此操作的代码如下所示:

always @ (posedge clk) begin
    if(shiftIndex == 0) begin
        if(dataValid == 1) transmitting = 1; //Blocking assign
        else transmitting = 0; //Blocking assign
    end

   //Need the blocking assign up above to get this part to run
   //for the 1st bit
   if(transmitting == 1) begin
       shiftIndex <= shiftIndex + 1;
       dataOut <= data5b[shiftIndex];

       if(shiftIndex == 4) begin
           complete <= 1;
           shiftIndex <= 0;
       end
       else begin
           complete <= …
Run Code Online (Sandbox Code Playgroud)

verilog

5
推荐指数
1
解决办法
6328
查看次数